JMeter-WebSocketSampler
JMeter-WebSocketSampler copied to clipboard
How to emit an event with data?
We are using socket.io as our implementation framework.
In javascript we execute following code after the connection has been established.
socket.emit('listenNotifications', { userId: 3 }, onListenCallback);
From the google Developer tools I see following message is sent.
5:1+::{"name":"listenNotifications","args":[{"userId":3}]}
How can we do this in the jsmeter sampler?
I can send you example JMX file if you want. The clue here is to simulate the socket IO communication. If you want to create it on your own please see this spec: https://github.com/LearnBoost/socket.io-spec
You need take care about the initialization, connection, connection closing etc. You need also to grab the session ID and pass it to your samplers.
You can also use google chrome and see how communication works. Only this browser have support to see communication details.
It would be awesome if you could send me an example... Currently we have an issue with sockets getting disconnected after a while. I managed to send the message, just copy pasted from chrome dev tools.
Thanks for your quick response.
Kind regards,
Marco Franssen
-----Original Message----- From: "filipcynarski" [email protected] Sent: 2-4-2014 14:00 To: "maciejzaleski/JMeter-WebSocketSampler" [email protected] Cc: "Marco Franssen" [email protected] Subject: Re: [JMeter-WebSocketSampler] How to emit an event with data? (#20)
I can send you example JMX file if you want. The clue here is to simulate the socket IO communication. I you want to create it on your own please see this spec: https://github.com/LearnBoost/socket.io-spec You need take care about the initialization, connection, closing connection etc. You need also to grab the session ID and pass it to your samplers. — Reply to this email directly or view it on GitHub.
Here is the content of sample JMX file. Just copy and paste and open it w/ JMeter.
I've set project variables: hots and referrer (referrer is not required and probably you can remove it from all places where it is present in load test project, however it was used by logic which I've examined so it remains here) you need to adjust them to URLs which you are calling. You can add the Tree View listener to see communication.
My example works as a streaming and logic which I'm examining is sending messages during 30 seconds time period so I've put delay on connection close - just to receive more messages.
It is just en example how you can use this extension feel free to modify, change or adjust to your expectations.
<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="2.6" jmeter="2.11 r1554548">
<hashTree>
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="SocketIO Example" enabled="true">
<stringProp name="TestPlan.comments"></stringProp>
<boolProp name="TestPlan.functional_mode">false</boolProp>
<boolProp name="TestPlan.serialize_threadgroups">true</boolProp>
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments">
<elementProp name="referrer" elementType="Argument">
<stringProp name="Argument.name">referrer</stringProp>
<stringProp name="Argument.value">service URL</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
<elementProp name="host" elementType="Argument">
<stringProp name="Argument.name">host</stringProp>
<stringProp name="Argument.value">your host</stringProp>
<stringProp name="Argument.metadata">=</stringProp>
</elementProp>
</collectionProp>
</elementProp>
<stringProp name="TestPlan.user_define_classpath"></stringProp>
</TestPlan>
<hashTree>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="ExampleThread" enabled="true">
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
<boolProp name="LoopController.continue_forever">false</boolProp>
<stringProp name="LoopController.loops">1</stringProp>
</elementProp>
<stringProp name="ThreadGroup.num_threads">1</stringProp>
<stringProp name="ThreadGroup.ramp_time">10</stringProp>
<longProp name="ThreadGroup.start_time">1394811307000</longProp>
<longProp name="ThreadGroup.end_time">1394811307000</longProp>
<boolProp name="ThreadGroup.scheduler">false</boolProp>
<stringProp name="ThreadGroup.duration"></stringProp>
<stringProp name="ThreadGroup.delay"></stringProp>
<stringProp name="TestPlan.comments">SocketIO test</stringProp>
</ThreadGroup>
<hashTree>
<HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true">
<collectionProp name="HeaderManager.headers">
<elementProp name="" elementType="Header">
<stringProp name="Header.name">Host</stringProp>
<stringProp name="Header.value">${host}</stringProp>
</elementProp>
<elementProp name="" elementType="Header">
<stringProp name="Header.name">User-Agent</stringProp>
<stringProp name="Header.value">Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.102 Safari/537.36</stringProp>
</elementProp>
<elementProp name="" elementType="Header">
<stringProp name="Header.name">Accept</stringProp>
<stringProp name="Header.value">text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8</stringProp>
</elementProp>
<elementProp name="" elementType="Header">
<stringProp name="Header.name">Accept-Language</stringProp>
<stringProp name="Header.value">en-US,en;q=0.5</stringProp>
</elementProp>
<elementProp name="" elementType="Header">
<stringProp name="Header.name">Accept-Encoding</stringProp>
<stringProp name="Header.value">gzip,deflate,sdch</stringProp>
</elementProp>
<elementProp name="" elementType="Header">
<stringProp name="Header.name">Connection</stringProp>
<stringProp name="Header.value">keep-alive</stringProp>
</elementProp>
<elementProp name="" elementType="Header">
<stringProp name="Header.name">Referrer</stringProp>
<stringProp name="Header.value">${referrer}</stringProp>
</elementProp>
</collectionProp>
</HeaderManager>
<hashTree/>
<BSFPreProcessor guiclass="TestBeanGUI" testclass="BSFPreProcessor" testname="BSF PreProcessor" enabled="true">
<stringProp name="filename"></stringProp>
<stringProp name="parameters"></stringProp>
<stringProp name="script">vars.put('timestamp', Math.round(new Date().getTime()) );</stringProp>
<stringProp name="scriptLanguage">javascript</stringProp>
</BSFPreProcessor>
<hashTree/>
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="SocketIO session get" enabled="true">
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="HTTPSampler.domain">${host}</stringProp>
<stringProp name="HTTPSampler.port"></stringProp>
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
<stringProp name="HTTPSampler.response_timeout"></stringProp>
<stringProp name="HTTPSampler.protocol"></stringProp>
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
<stringProp name="HTTPSampler.path">socket.io/1/?t=${timestamp}</stringProp>
<stringProp name="HTTPSampler.method">GET</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
<stringProp name="HTTPSampler.implementation">HttpClient4</stringProp>
<boolProp name="HTTPSampler.monitor">false</boolProp>
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
</HTTPSamplerProxy>
<hashTree>
<RegexExtractor guiclass="RegexExtractorGui" testclass="RegexExtractor" testname="Regular Expression Extractor" enabled="true">
<stringProp name="RegexExtractor.useHeaders">false</stringProp>
<stringProp name="RegexExtractor.refname">sessionid</stringProp>
<stringProp name="RegexExtractor.regex">[^:]*</stringProp>
<stringProp name="RegexExtractor.template">$0$</stringProp>
<stringProp name="RegexExtractor.default">empty</stringProp>
<stringProp name="RegexExtractor.match_number">1</stringProp>
</RegexExtractor>
<hashTree/>
</hashTree>
<JMeter.plugins.functional.samplers.websocket.WebSocketSampler guiclass="JMeter.plugins.functional.samplers.websocket.WebSocketSamplerGui" testclass="JMeter.plugins.functional.samplers.websocket.WebSocketSampler" testname="Initialize SocketIO connection" enabled="true">
<stringProp name="serverAddress">${host}</stringProp>
<stringProp name="serverPort">80</stringProp>
<stringProp name="implementation">RFC6455 (v13)</stringProp>
<stringProp name="protocol">ws</stringProp>
<stringProp name="contextPath">socket.io/1/websocket/${sessionid}</stringProp>
<stringProp name="contentEncoding">UTF-8</stringProp>
<stringProp name="requestPayload">1::</stringProp>
<stringProp name="connectionTimeout">10000</stringProp>
<stringProp name="responseTimeout">20000</stringProp>
<boolProp name="ignoreSslErrors">false</boolProp>
<boolProp name="streamingConnection">true</boolProp>
<stringProp name="connectionId">${sessionid}</stringProp>
<stringProp name="responsePattern">.*</stringProp>
<stringProp name="closeConncectionPattern">0::*</stringProp>
<stringProp name="proxyAddress"></stringProp>
<stringProp name="proxyPassword"></stringProp>
<stringProp name="proxyPort"></stringProp>
<stringProp name="proxyUsername"></stringProp>
<stringProp name="messageBacklog">10</stringProp>
<elementProp name="queryStringParameters" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
</JMeter.plugins.functional.samplers.websocket.WebSocketSampler>
<hashTree/>
<JMeter.plugins.functional.samplers.websocket.WebSocketSampler guiclass="JMeter.plugins.functional.samplers.websocket.WebSocketSamplerGui" testclass="JMeter.plugins.functional.samplers.websocket.WebSocketSampler" testname="SocketIO HeartBeat" enabled="true">
<stringProp name="serverAddress">${host}</stringProp>
<stringProp name="serverPort">80</stringProp>
<stringProp name="implementation">RFC6455 (v13)</stringProp>
<stringProp name="protocol">ws</stringProp>
<stringProp name="contextPath">socket.io/1/websocket/${sessionid}</stringProp>
<stringProp name="contentEncoding">UTF-8</stringProp>
<stringProp name="requestPayload">2::</stringProp>
<stringProp name="connectionTimeout">10000</stringProp>
<stringProp name="responseTimeout">20000</stringProp>
<boolProp name="ignoreSslErrors">false</boolProp>
<boolProp name="streamingConnection">true</boolProp>
<stringProp name="connectionId">${sessionid}</stringProp>
<stringProp name="responsePattern">.*</stringProp>
<stringProp name="closeConncectionPattern">0::*</stringProp>
<stringProp name="proxyAddress"></stringProp>
<stringProp name="proxyPassword"></stringProp>
<stringProp name="proxyPort"></stringProp>
<stringProp name="proxyUsername"></stringProp>
<stringProp name="messageBacklog">10</stringProp>
<elementProp name="queryStringParameters" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
</JMeter.plugins.functional.samplers.websocket.WebSocketSampler>
<hashTree/>
<JMeter.plugins.functional.samplers.websocket.WebSocketSampler guiclass="JMeter.plugins.functional.samplers.websocket.WebSocketSamplerGui" testclass="JMeter.plugins.functional.samplers.websocket.WebSocketSampler" testname="SocketIO subscribe" enabled="true">
<stringProp name="serverAddress">${host}</stringProp>
<stringProp name="serverPort">80</stringProp>
<stringProp name="implementation">RFC6455 (v13)</stringProp>
<stringProp name="protocol">ws</stringProp>
<stringProp name="contextPath">socket.io/1/websocket/${sessionid}</stringProp>
<stringProp name="contentEncoding">UTF-8</stringProp>
<stringProp name="requestPayload">5:::{"name":"subscribe"}</stringProp>
<stringProp name="connectionTimeout">10000</stringProp>
<stringProp name="responseTimeout">20000</stringProp>
<boolProp name="ignoreSslErrors">false</boolProp>
<boolProp name="streamingConnection">true</boolProp>
<stringProp name="connectionId">${sessionid}</stringProp>
<stringProp name="responsePattern">.*</stringProp>
<stringProp name="closeConncectionPattern">0::*</stringProp>
<stringProp name="proxyAddress"></stringProp>
<stringProp name="proxyPassword"></stringProp>
<stringProp name="proxyPort"></stringProp>
<stringProp name="proxyUsername"></stringProp>
<stringProp name="messageBacklog">10</stringProp>
<elementProp name="queryStringParameters" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
</JMeter.plugins.functional.samplers.websocket.WebSocketSampler>
<hashTree/>
<JMeter.plugins.functional.samplers.websocket.WebSocketSampler guiclass="JMeter.plugins.functional.samplers.websocket.WebSocketSamplerGui" testclass="JMeter.plugins.functional.samplers.websocket.WebSocketSampler" testname="SocketIO disconnect" enabled="true">
<stringProp name="serverAddress">${host}</stringProp>
<stringProp name="serverPort">80</stringProp>
<stringProp name="implementation">RFC6455 (v13)</stringProp>
<stringProp name="protocol">ws</stringProp>
<stringProp name="contextPath">socket.io/1/websocket/${sessionid}</stringProp>
<stringProp name="contentEncoding">UTF-8</stringProp>
<stringProp name="requestPayload">0::</stringProp>
<stringProp name="connectionTimeout">10000</stringProp>
<stringProp name="responseTimeout">20000</stringProp>
<boolProp name="ignoreSslErrors">false</boolProp>
<boolProp name="streamingConnection">true</boolProp>
<stringProp name="connectionId">${sessionid}</stringProp>
<stringProp name="responsePattern">.*</stringProp>
<stringProp name="closeConncectionPattern">0::*</stringProp>
<stringProp name="proxyAddress"></stringProp>
<stringProp name="proxyPassword"></stringProp>
<stringProp name="proxyPort"></stringProp>
<stringProp name="proxyUsername"></stringProp>
<stringProp name="messageBacklog">10</stringProp>
<elementProp name="queryStringParameters" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
</JMeter.plugins.functional.samplers.websocket.WebSocketSampler>
<hashTree>
<ConstantTimer guiclass="ConstantTimerGui" testclass="ConstantTimer" testname="Constant Timer" enabled="true">
<stringProp name="ConstantTimer.delay">8000</stringProp>
</ConstantTimer>
<hashTree/>
</hashTree>
</hashTree>
</hashTree>
</hashTree>
</jmeterTestPlan>
BTW I've found that this plugin is not ready to examine services w/ high load or soak testing it requires to some fixes on author side however it is better than nothing. You can always do some coding and fix this plugin as well.
@marcofranssen , can you share your socket.io example if was successful ?
@filipcynarski , How to solve this problem? http://stackoverflow.com/questions/39101808/how-to-emit-an-event-in-jmeter?