JMeter
Sisukord
Sissejuhatus
JMeter http://jakarta.apache.org/jmeter/ tarkvara abil saab testida kuidas veebiserver ja sinna paigaldatud rakendus käitub kui talle esitada erinevaid http päringuid. Lisaks päringute esitamisele võimaldab JMeter analüüsida testi käigus kogutud andmeid, mh esitada tulemust graafiliselt.
JMeter on java programm.
Tarkvara kasutamiseks ettevalmistamine
JMeter tarkvara sobib kasutada praktiliselt suvalise operatsioonisüsteemiga, kuhu on paigaldatud graafiline kasutajaliides ning kus on olemas JVM (Java Virtual Machine, st Java). Kasutamiseks tuleb kopeerida JMeter veebikohast nt kompileeritud .tar.gz fail, pakkida sobivasse kataloogi lahti, seada JAVA_HOME keskkonnamuutuja
# cd /usr/local # tar zxf jakarta-jmeter-2.3.2.tgz
JMeter käivitamiseks tuleb öelda
$ export JAVA_HOME=/tee/java/kataloogi $ /usr/local/jakarta-jmeter-2.3.2/bin/jmeter.sh
Testi kirjeldamine
Parema klõpsu Test Plan peal valime "add" ja lisame "Thread Group"
Oluline seadistada Thread Group alt paremeetrid
- Number of Threads (users)
- Ramp-Up period (in seconds)
Seejärel lisame selle alla Kontrolleri. Valime "Thread Group" peal parema klahvi alt või menüüst
edit > add > Logic Controllers > Simple Controller
Lisame HTTP testi "HTTP Request"
edit > add > Sampler > Httpd request
Valime selle hiirega ja lisame HTTP Request alla serveri nime ja urli.
Ehk kui palju kasutajaid ja millise intervalliga
Tulemuste tekstilisel kujul nägemiseks tuleb lisada Thread Group alla "view results in table"
edit > add > listener > view results in table
Ja soovides vaadata ka graafikuid tuleb öelda
edit > add > listener > graph results
Simuleerides ühe kasutaja F5 vajutamist võib kasutada HTTP Cookie Mangeri, kui simuleerides paljusid erinevaid kasutajaid pole seda vaja või on ta pigem lisatüliks.
Sisufilter ehk Response Assertion
Probleem võib tekkida, et veebiserver ja veeb annavad isegi vastuse kuid suure koormusega mingid komponendid tegelikult ei tööta
Soovides kontrollida vastuslehtedest mingi teate olemasolu. Näiteks vaadata, et ega seal oleks olemas mingi vajalik tekst. Tuleb tekitada "Response Assertion"
edit > add > assertion
Valida Text Response substring, contains ja "Pattern to Test" kasti tuleb lisada nt "Teretulemas veebilehele" vms mis veebilehel normaalsel töötamisel kasutajal kuvatakse.
Kõik mis patternile mittevasatavad lisatakse Summary Report tabelis Error % juurde.
Võimalik on otsida ka erroreid nt lülitades "substring" ja "not" sisse kuid veeb võib tugeva koormuse alla anda palju erinevaid veateateid ja neid kõiki defineerida ajamahukas.
Suvaline muutuja
Võimalik on kasutada ka muutujat "Random Variable", ehk anda veebilehele ette erineva kasutaja id nt. See on hea selleks, et iga päring mis veebilehele tehakse oleks erinev ning nii ei saaks andmebaasimootor või proxy lihtsalt ühte päringut cacheda.
Random Variable juures tuleb määrata esiteks Muutuja nimi ja teiseks Minimum ja Maximum value ehk väärtus millede vahel neid numbreid genereeritakse.
Kasutamiseks tuleb HTTP Request blokis määrata Path real ${muutuja} kujul. Näiteks
/veebileht/index.php?token=${muutuja}
Teste on võimalik peale koostamist salvestada XML formaati ja kasutada hiljemgi.
Graafikud
Tundub, et response time graph on üks informatiivseim, mida tasuks kasutada. Interval mis millisekundites tasuks seadistada 1000 peale.
Testi käivitamine
Run > Start
tulemused ilmuvad Graph Result ja Summary Report alla, võimalus on salvestada tulemused ka faili ning isegi kõik päringute vastused.
Üks olulisemaid numbreid on Error % ja Troughput mis näitab suur oli veaga vastuseid ja palju päringuid sekundis läbi läks.
Konfiguratsioon
Eksporditud valmis konfiguratsioon näeb välja järgnev:
<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="2.1">
<hashTree>
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true">
<stringProp name="TestPlan.comments"></stringProp>
<boolProp name="TestPlan.functional_mode">false</boolProp>
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="TestPlan.user_define_classpath"></stringProp>
</TestPlan>
<hashTree>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group" 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">20</stringProp>
</elementProp>
<stringProp name="ThreadGroup.num_threads">1000</stringProp>
<stringProp name="ThreadGroup.ramp_time">5</stringProp>
<longProp name="ThreadGroup.start_time">1294222229000</longProp>
<longProp name="ThreadGroup.end_time">1294222229000</longProp>
<boolProp name="ThreadGroup.scheduler">false</boolProp>
<stringProp name="ThreadGroup.duration"></stringProp>
<stringProp name="ThreadGroup.delay"></stringProp>
</ThreadGroup>
<hashTree>
<HTTPSampler guiclass="HttpTestSampleGui" testclass="HTTPSampler" testname="HTTP Request" enabled="true">
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="HTTPSampler.domain"></stringProp>
<stringProp name="HTTPSampler.port"></stringProp>
<stringProp name="HTTPSampler.connect_timeout">60000</stringProp>
<stringProp name="HTTPSampler.response_timeout">300000</stringProp>
<stringProp name="HTTPSampler.protocol"></stringProp>
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
<stringProp name="HTTPSampler.path">/limesurvey/index.php?sid=75455&lang=et</stringProp>
<stringProp name="HTTPSampler.method">GET</stringProp>
<boolProp name="HTTPSampler.follow_redirects">false</boolProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
<boolProp name="HTTPSampler.image_parser">true</boolProp>
<boolProp name="HTTPSampler.monitor">false</boolProp>
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
</HTTPSampler>
<hashTree/>
<ConfigTestElement guiclass="HttpDefaultsGui" testclass="ConfigTestElement" testname="HTTP Request Defaults" enabled="true">
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="HTTPSampler.domain">zoo.tartu.ee</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"></stringProp>
</ConfigTestElement>
<hashTree/>
<CookieManager guiclass="CookiePanel" testclass="CookieManager" testname="HTTP Cookie Manager" enabled="true">
<collectionProp name="CookieManager.cookies"/>
<boolProp name="CookieManager.clearEachIteration">false</boolProp>
<stringProp name="CookieManager.policy">rfc2109</stringProp>
</CookieManager>
<hashTree/>
</hashTree>
<ResultCollector guiclass="GraphVisualizer" testclass="ResultCollector" testname="Graph Results" enabled="true">
<boolProp name="ResultCollector.error_logging">false</boolProp>
<objProp>
<name>saveConfig</name>
<value class="SampleSaveConfiguration">
<time>true</time>
<latency>true</latency>
<timestamp>true</timestamp>
<success>true</success>
<label>true</label>
<code>true</code>
<message>true</message>
<threadName>true</threadName>
<dataType>true</dataType>
<encoding>false</encoding>
<assertions>true</assertions>
<subresults>true</subresults>
<responseData>false</responseData>
<samplerData>false</samplerData>
<xml>true</xml>
<fieldNames>false</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
<bytes>true</bytes>
</value>
</objProp>
<stringProp name="filename"></stringProp>
</ResultCollector>
<hashTree/>
<ResultCollector guiclass="SummaryReport" testclass="ResultCollector" testname="Summary Report" enabled="true">
<boolProp name="ResultCollector.error_logging">false</boolProp>
<objProp>
<name>saveConfig</name>
<value class="SampleSaveConfiguration">
<time>true</time>
<latency>true</latency>
<timestamp>true</timestamp>
<success>true</success>
<label>true</label>
<code>true</code>
<message>true</message>
<threadName>true</threadName>
<dataType>true</dataType>
<encoding>false</encoding>
<assertions>true</assertions>
<subresults>true</subresults>
<responseData>false</responseData>
<samplerData>false</samplerData>
<xml>true</xml>
<fieldNames>false</fieldNames>
<responseHeaders>false</responseHeaders>
<requestHeaders>false</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
<bytes>true</bytes>
</value>
</objProp>
<stringProp name="filename"></stringProp>
</ResultCollector>
<hashTree/>
</hashTree>
</hashTree>
</jmeterTestPlan>