简体   繁体   中英

Running Jmeter Webdriver test using Docker gives me CannotResolveClassException

I made one test using JMeter and the Webdriver plugin that works on my local machine, but this same test is not working when running against a Docker container.

First some background, i run the jobs with Jenkins, and for every JMeter job, i need to create the csv file with all the user data for the test, i made a CLI application in java 11 that make that. Then i run jmeter in CLI mode inside the same container.

Here's the dockerfile i used, FROM the "selenium/standalone-chrome-debug" so i have google-chrome-stable and chromedriver binaries in the container:

FROM selenium/standalone-chrome-debug:latest

EXPOSE 5900-6000
EXPOSE 4444-4544

# Install dependencies
USER root

# Install JDK
RUN apt-get -qq update
RUN apt-get -qq -y install software-properties-common
RUN \
  echo debconf shared/accepted-oracle-license-v1-2 select true | debconf-set-selections && \
  echo debconf shared/accepted-oracle-license-v1-2 seen true | debconf-set-selections && \
  add-apt-repository ppa:linuxuprising/java && \
  apt-get update && \
  apt-get install -qq -y oracle-java11-installer && \
  rm -rf /var/lib/apt/lists/* && \
  rm -rf /var/cache/oracle-java11-installer

# Install Maven
ARG MAVEN_VERSION=3.6.0
ARG USER_HOME_DIR="/root"
ARG SHA=6a1b346af36a1f1a491c1c1a141667c5de69b42e6611d3687df26868bc0f4637
ARG BASE_URL=https://apache.osuosl.org/maven/maven-3/${MAVEN_VERSION}/binaries

RUN mkdir -p /usr/share/maven /usr/share/maven/ref \
  && apt-get update \
  && apt-get -qq -y install curl \
  && curl -fsSL -o /tmp/apache-maven.tar.gz ${BASE_URL}/apache-maven-${MAVEN_VERSION}-bin.tar.gz \
  && echo "${SHA}  /tmp/apache-maven.tar.gz" | sha256sum -c - \
  && tar -xzf /tmp/apache-maven.tar.gz -C /usr/share/maven --strip-components=1 \
  && rm -f /tmp/apache-maven.tar.gz \
  && ln -s /usr/share/maven/bin/mvn /usr/bin/mvn

ENV MAVEN_HOME /usr/share/maven
ENV MAVEN_CONFIG "$USER_HOME_DIR/.m2"

# Install JMeter
ARG JMETER_VERSION="5.1.1"
ENV JMETER_HOME /opt/apache-jmeter-${JMETER_VERSION}
ENV JMETER_BIN  ${JMETER_HOME}/bin
ENV JMETER_DOWNLOAD_URL https://archive.apache.org/dist/jmeter/binaries/apache-jmeter-${JMETER_VERSION}.tgz
ENV JMETER_PLUGINS_MANAGER_VERSION 1.3
ENV CMDRUNNER_VERSION 2.2

RUN apt-get update && \
  apt-get install -qq -y curl unzip && \
  mkdir -p /tmp/dependencies && \
  curl -L --silent ${JMETER_DOWNLOAD_URL} > /tmp/dependencies/apache-jmeter-${JMETER_VERSION}.tgz && \
  mkdir -p /opt && \
  tar -xzf /tmp/dependencies/apache-jmeter-${JMETER_VERSION}.tgz -C /opt && \
  rm -rf /tmp/dependencies

# Set global PATH such that "jmeter" command is found
ENV PATH $PATH:$JMETER_BIN

# Install JMeter Plugins
RUN curl --location --silent --show-error --output ${JMETER_HOME}/lib/ext/jmeter-plugins-manager-${JMETER_PLUGINS_MANAGER_VERSION}.jar http://search.maven.org/remotecontent?filepath=kg/apc/jmeter-plugins-manager/${JMETER_PLUGINS_MANAGER_VERSION}/jmeter-plugins-manager-${JMETER_PLUGINS_MANAGER_VERSION}.jar \
 && curl --location --silent --show-error --output ${JMETER_HOME}/lib/cmdrunner-${CMDRUNNER_VERSION}.jar http://search.maven.org/remotecontent?filepath=kg/apc/cmdrunner/${CMDRUNNER_VERSION}/cmdrunner-${CMDRUNNER_VERSION}.jar \
 && curl --location --silent --show-error --output ${JMETER_HOME}/lib/json-lib-${JSON_LIB_FULL_VERSION}.jar https://search.maven.org/remotecontent?filepath=net/sf/json-lib/json-lib/${JSON_LIB_VERSION}/json-lib-${JSON_LIB_FULL_VERSION}.jar \
 && java -cp ${JMETER_HOME}/lib/ext/jmeter-plugins-manager-${JMETER_PLUGINS_MANAGER_VERSION}.jar org.jmeterplugins.repository.PluginManagerCMDInstaller \
 && PluginsManagerCMD.sh install-all-except

USER root

Here's the jmx file, "jp@gc - WebDriver Sampler" part (in Java code):

import org.openqa.selenium.*;
import org.openqa.selenium.support.ui.*;

WDS.sampleResult.sampleStart();

String baseUrl = WDS.vars.get("hostname");

WDS.browser.get(baseUrl + "/");

WebDriverWait wait = new WebDriverWait(WDS.browser, 10);
wait.until(ExpectedConditions.elementToBeClickable(WDS.browser.findElement(By.id("username"))));
wait.until(ExpectedConditions.elementToBeClickable(WDS.browser.findElement(By.id("password"))));
wait.until(ExpectedConditions.elementToBeClickable(WDS.browser.findElement(By.id("enterButton"))));

WDS.sampleResult.sampleEnd();

Here's the config section of the ChromeDriver:

<com.googlecode.jmeter.plugins.webdriver.config.ChromeDriverConfig guiclass="com.googlecode.jmeter.plugins.webdriver.config.gui.ChromeDriverConfigGui" testclass="com.googlecode.jmeter.plugins.webdriver.config.ChromeDriverConfig" testname="jp@gc - Chrome Driver Config" enabled="true">
        <stringProp name="WebDriverConfig.proxy_type">SYSTEM</stringProp>
        <stringProp name="WebDriverConfig.proxy_pac_url"></stringProp>
        <stringProp name="WebDriverConfig.http_host"></stringProp>
        <intProp name="WebDriverConfig.http_port">8080</intProp>
        <boolProp name="WebDriverConfig.use_http_for_all_protocols">true</boolProp>
        <stringProp name="WebDriverConfig.https_host"></stringProp>
        <intProp name="WebDriverConfig.https_port">8080</intProp>
        <stringProp name="WebDriverConfig.ftp_host"></stringProp>
        <intProp name="WebDriverConfig.ftp_port">8080</intProp>
        <stringProp name="WebDriverConfig.socks_host"></stringProp>
        <intProp name="WebDriverConfig.socks_port">8080</intProp>
        <stringProp name="WebDriverConfig.no_proxy">localhost</stringProp>
        <boolProp name="WebDriverConfig.maximize_browser">true</boolProp>
        <boolProp name="WebDriverConfig.reset_per_iteration">false</boolProp>
        <boolProp name="WebDriverConfig.dev_mode">false</boolProp>
        <stringProp name="ChromeDriverConfig.chromedriver_path">${__P(browser_path,/usr/bin/chromedriver)}</stringProp>
        <boolProp name="ChromeDriverConfig.android_enabled">false</boolProp>
        <boolProp name="ChromeDriverConfig.headless_enabled">true</boolProp>
        <boolProp name="ChromeDriverConfig.insecurecerts_enabled">false</boolProp>
      </com.googlecode.jmeter.plugins.webdriver.config.ChromeDriverConfig>

Then build the image and run the jmeter test with these commands:

$ docker build -t docker/chromejmeter -f docker/DockerfileChromeDebugJmeter docker/

$ docker run --env 'JVM_ARGS=-Xms2048m -Xmx2048m -XX:NewSize=2048m -XX:MaxNewSize=2048m' -v `pwd`:`pwd` -w `pwd` --name TestWebChromeJmeter docker/chromejmeter jmeter -n -Jdatasource_file=user_data.csv -t src/test/jmeter/testPlans/plans/Web_Login_UserLogin_Test.jmx -l src/test/jmeter/reports/Web_Login_UserLogin_Test.jtl

But i get the following error:

Error in NonGUIDriver java.lang.IllegalArgumentException: Problem loading XML from:'/home/lea/repos/automation/src/test/jmeter/testPlans/plans/WebWebclient_Login_UserLogin_Test.jmx'.
Cause:
CannotResolveClassException: com.googlecode.jmeter.plugins.webdriver.config.ChromeDriverConfig

 Detail:com.thoughtworks.xstream.converters.ConversionException:
---- Debugging information ----
cause-exception     : com.thoughtworks.xstream.converters.ConversionException
cause-message       :
first-jmeter-class  : org.apache.jmeter.save.converters.HashTreeConverter.unmarshal(HashTreeConverter.java:67)
class               : org.apache.jmeter.save.ScriptWrapper
required-type       : org.apache.jmeter.save.ScriptWrapper
converter-type      : org.apache.jmeter.save.ScriptWrapperConverter
path                : /jmeterTestPlan/hashTree/hashTree/com.googlecode.jmeter.plugins.webdriver.config.ChromeDriverConfig
line number         : 57
version             : 5.1.1 r1855137
-------------------------------

If i run the same test without docker, it works ok:

$ export JVM_ARGS="-Xms2048m -Xmx2048m -XX:NewSize=2048m -XX:MaxNewSize=2048m" && jmeter -n -Jhostname=
https://my.site.com.ar -Jdatasource_file=user_data.cvs -t src/test/jmeter/testPlans/plans/Web_Login_UserLogin_Test.jmx -l src/test/jmeter/reports/Web_Login_UserLogin_Test.Jtl
Creating summariser <summary>
Created the tree successfully using src/test/jmeter/testPlans/plans/WebWebclient_Login_UserLogin_Test.jmx
Starting the test @ Wed May 08 09:26:45 ART 2019 (1557318405559)
Waiting for possible Shutdown/StopTestNow/HeapDump/ThreadDump message on port 4445
Warning: Nashorn engine is planned to be removed from a future JDK release
Starting ChromeDriver 74.0.3729.6 (255758eccf3d244491b8a1317aa76e1ce10d57e9-refs/branch-heads/3729@{#29}) on port 20152
Only local connections are allowed.
Please protect ports used by ChromeDriver and related test frameworks to prevent access by malicious code.
May 08, 2019 9:26:46 AM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: OSS
summary =      2 in 00:00:12 =    0.2/s Avg:  5283 Min:   899 Max:  9667 Err:     1 (50.00%)
Tidying up ...    @ Wed May 08 09:26:57 ART 2019 (1557318417720)
... end of run

I made some changes to the above file and it worked perfectly fine. Hopefully It helps you

So here the changes would happen on the jmeter build you have to use as time proceeds. Make sure you give the correct sha256sum in the dockerfile and this depends upon the version of jmeter you are using for the docker image.

Dockerfile is as below

FROM selenium/standalone-chrome-debug
EXPOSE 5900-6000
EXPOSE 4444-4544

# Install dependencies
USER root

# Install JDK
RUN apt-get -qq update
RUN apt-get -qq -y install software-properties-common
RUN \
  echo debconf shared/accepted-oracle-license-v1-2 select true | debconf-set-selections && \
  echo debconf shared/accepted-oracle-license-v1-2 seen true | debconf-set-selections && \
  add-apt-repository ppa:linuxuprising/java && \
  apt-get update && \
  apt-get install -qq -y default-jdk && \
  rm -rf /var/lib/apt/lists/* && \
  rm -rf /var/cache/oracle-java11-installer

# Install Maven
ARG MAVEN_VERSION=3.6.2
ARG USER_HOME_DIR="/root"
ARG SHA=3fbc92d1961482d6fbd57fbf3dd6d27a4de70778528ee3fb44aa7d27eb32dfdc
ARG BASE_URL=https://apache.osuosl.org/maven/maven-3/${MAVEN_VERSION}/binaries

RUN mkdir -p /usr/share/maven /usr/share/maven/ref \
  && apt-get update \
  && apt-get -qq -y install curl \
  && curl -fsSL -o /tmp/apache-maven.tar.gz ${BASE_URL}/apache-maven-${MAVEN_VERSION}-bin.tar.gz \
  && echo "${SHA}  /tmp/apache-maven.tar.gz" | sha256sum -c - \
  && tar -xzf /tmp/apache-maven.tar.gz -C /usr/share/maven --strip-components=1 \
  && rm -f /tmp/apache-maven.tar.gz \
  && ln -s /usr/share/maven/bin/mvn /usr/bin/mvn

ENV MAVEN_HOME /usr/share/maven
ENV MAVEN_CONFIG "$USER_HOME_DIR/.m2"

# Install JMeter
ARG JMETER_VERSION="5.1.1"
ENV JMETER_HOME /opt/apache-jmeter-${JMETER_VERSION}
ENV JMETER_BIN  ${JMETER_HOME}/bin
ENV JMETER_DOWNLOAD_URL https://archive.apache.org/dist/jmeter/binaries/apache-jmeter-${JMETER_VERSION}.tgz
ENV JMETER_PLUGINS_MANAGER_VERSION 1.3
ENV CMDRUNNER_VERSION 2.2

RUN apt-get update && \
  apt-get install -qq -y curl unzip && \
  mkdir -p /tmp/dependencies && \
  curl -L --silent ${JMETER_DOWNLOAD_URL} > /tmp/dependencies/apache-jmeter-${JMETER_VERSION}.tgz && \
  mkdir -p /opt && \
  tar -xzf /tmp/dependencies/apache-jmeter-${JMETER_VERSION}.tgz -C /opt && \
  rm -rf /tmp/dependencies

# Set global PATH such that "jmeter" command is found
ENV PATH $PATH:$JMETER_BIN

# Install JMeter Plugins
RUN curl --location --silent --show-error --output ${JMETER_HOME}/lib/ext/jmeter-plugins-manager-${JMETER_PLUGINS_MANAGER_VERSION}.jar http://search.maven.org/remotecontent?filepath=kg/apc/jmeter-plugins-manager/${JMETER_PLUGINS_MANAGER_VERSION}/jmeter-plugins-manager-${JMETER_PLUGINS_MANAGER_VERSION}.jar \
 && curl --location --silent --show-error --output ${JMETER_HOME}/lib/cmdrunner-${CMDRUNNER_VERSION}.jar http://search.maven.org/remotecontent?filepath=kg/apc/cmdrunner/${CMDRUNNER_VERSION}/cmdrunner-${CMDRUNNER_VERSION}.jar \
 && curl --location --silent --show-error --output ${JMETER_HOME}/lib/json-lib-${JSON_LIB_FULL_VERSION}.jar https://search.maven.org/remotecontent?filepath=net/sf/json-lib/json-lib/${JSON_LIB_VERSION}/json-lib-${JSON_LIB_FULL_VERSION}.jar \
 && java -cp ${JMETER_HOME}/lib/ext/jmeter-plugins-manager-${JMETER_PLUGINS_MANAGER_VERSION}.jar org.jmeterplugins.repository.PluginManagerCMDInstaller \
 &&  JVM_ARGS="-Dhttps.proxyHost=<proxyhost> -Dhttps.proxyPort=80"  PluginsManagerCMD.sh install-all-except

RUN curl --location --silent --show-error --output  ${JMETER_HOME}/lib/guava-19.0.0.jar http://search.maven.org/remotecontent?filepath=com/google/guava/guava/22.0/guava-22.0.jar

COPY launch.sh /

WORKDIR ${JMETER_HOME}

ENTRYPOINT ["/launch.sh"]

launch.sh has the following code

#!/bin/bash

set -e
freeMem=`awk '/MemFree/ { print int($2/1024) }' /proc/meminfo`
s=$(($freeMem/10*8))
x=$(($freeMem/10*8))
n=$(($freeMem/10*2))
export JVM_ARGS="-Xmn${n}m -Xms${s}m -Xmx${x}m"

echo "JVM_ARGS=${JVM_ARGS}"
echo "jmeter args=$@"

jmeter $@

For the chromedriver config make sure that you added the correct path the of the driver

Now here comes the answer for the issue you faced. That is the way you called the jmeter container.

export volume_path="<give the path to the folder  where you have your jmx file>" && export jmeter_path="<give the path within your container>" && docker run --name jmeter_${NOW} --volume "${volume_path}":${jmeter_path} jmeterdocker   -n    -t ${jmeter_path}/<name of your jmx file>   -l tmp/result_${NOW}.jtl   -j tmp/jmeter_${NOW}.log

The above command is copying all the files under your volume_path to the jmeter_path which is within the container. Now the .jtl and the .log file is created and kept under the jmeter bin folder as the container is currently at that path as per the launch.sh

Now to get the log files from the container you could later use docker cp command.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM