我使用 JMeter 和可在本地计算机上运行的 Webdriver 插件进行了一项测试,但在针对 Docker 容器运行时,相同的测试不起作用。
首先是一些背景知识,我使用 Jenkins 运行作业,对于每个 JMeter 作业,我需要创建包含所有测试用户数据的 csv 文件,我在 java 11 中创建了一个 CLI 应用程序来实现这一点。然后我在同一个容器内以 CLI 模式运行 jmeter。
这是我使用的 dockerfile,来自“selenium/standalone-chrome-debug”,所以我在容器中有 google-chrome-stable 和 chromedriver 二进制文件:
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
这是 jmx 文件,“jp@gc - WebDriver Sampler”部分(Java 代码):
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();
这是 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>
然后构建图像并使用以下命令运行 jmeter 测试:
$ 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
但是我收到以下错误:
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
-------------------------------
如果我在没有 docker 的情况下运行相同的测试,它工作正常:
$ 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
我对上面的文件做了一些更改,它工作得很好。希望对你有帮助
因此,随着时间的推移,您必须使用的 jmeter 构建将发生变化。确保您在 dockerfile 中提供了正确的 sha256sum,这取决于您用于 docker 映像的 jmeter 版本。
Dockerfile如下
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 有以下代码
#!/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 $@
对于 chromedriver 配置,请确保添加了驱动程序的正确路径
现在您所面临的问题的答案来了。这就是你调用 jmeter 容器的方式。
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
上面的命令是将volume_path下的所有文件复制到容器内的jmeter_path。现在,.jtl 和 .log 文件已创建并保存在 jmeter bin 文件夹下,因为容器当前根据 launch.sh 位于该路径
现在要从容器中获取日志文件,稍后可以使用 docker cp 命令。
如何创建 SHA 参数的值?