JMeter安裝+性能測試流程

Jmeter簡介

Apache JMeter是一款純java編寫負載功能測試和性能測試開源工具軟件。相比Loadrunner而言,JMeter小巧輕便且免費,逐漸成爲了主流的性能測試工具,是每個測試人員都必須要掌握的工具之一。

本文爲JMeter性能測試完整入門篇,從Jmeter下載安裝到編寫一個完整性能測試腳本、最終執行性能測試並分析性能測試結果。

運行環境爲Windows 10系統,JDK版本爲1.8,JMeter版本爲3.3。

Jmeter安裝

JDK安裝

由於Jmeter是基於java開發,首先需要下載安裝JDK (目前JMeter只支持到Java 8,尚不支持 Java 9)
1. 官網下載地址:http://www.oracle.com/technetwork/java/javase/downloads/index.html
2. 選擇Java SE 8u151/ 8u152,點擊JDK下載

3. 安裝下載的JDK
4. 配置系統環境變量

JMeter安裝

  • 下載完成後解壓zip包
  • 啓動JMeter
    雙擊JMeter解壓路徑(apache-jmeter-5.2\bin)bin下面的jmeter.bat即可

JMeter腳本編寫

添加線程組

右鍵點擊“測試計劃” -> “添加” -> “線程(用戶)或Threads(Users)” -> “線程組”

這裏可以配置線程組名稱,線程數,準備時長(Ramp-Up Period(in seconds))循環次數,調度器等參數:

線程組參數詳解:
1. 線程數:虛擬用戶數。一個虛擬用戶佔用一個進程或線程。設置多少虛擬用戶數在這裏也就是設置多少個線程數。
2. Ramp-Up Period(in seconds)準備時長:設置的虛擬用戶數需要多長時間全部啓動。如果線程數爲10,準備時長爲2,那麼需要2秒鐘啓動10個線程,也就是每秒鐘啓動5個線程。
3. 循環次數:每個線程發送請求的次數。如果線程數爲10,循環次數爲100,那麼每個線程發送100次請求。總請求數爲10*100=1000 。如果勾選了“永遠”,那麼所有線程會一直髮送請求,一到選擇停止運行腳本。
4. Delay Thread creation until needed:直到需要時延遲線程的創建。
5. 調度器:設置線程組啓動的開始時間和結束時間(配置調度器時,需要勾選循環次數爲永遠)
持續時間(秒):測試持續時間,會覆蓋結束時間
啓動延遲(秒):測試延遲啓動時間,會覆蓋啓動時間
啓動時間:測試啓動時間,啓動延遲會覆蓋它。當啓動時間已過,手動只需測試時當前時間也會覆蓋它。
結束時間:測試結束時間,持續時間會覆蓋它。

因爲接口調試需要,我們暫時均使用默認設置,待後面真正執行性能測試時再回來配置。
 

添加HTTP請求

右鍵點擊“線程組” -> “添加” -> “取樣器或Sampler” -> “HTTP請求”

Http請求主要參數詳解:

    Web服務器
    協議:向目標服務器發送HTTP請求協議,可以是HTTP或HTTPS,默認爲HTTP
    服務器名稱或IP :HTTP請求發送的目標服務器名稱或IP
    端口號:目標服務器的端口號,默認值爲80
    2.Http請求
    方法:發送HTTP請求的方法,可用方法包括GET、POST、HEAD、PUT、OPTIONS、TRACE、DELETE等。
    路徑:目標URL路徑(URL中去掉服務器地址、端口及參數後剩餘部分)
    Content encoding :編碼方式,默認爲ISO-8859-1編碼,這裏配置爲utf-8
    同請求一起發送參數
    在請求中發送的URL參數,用戶可以將URL中所有參數設置在本表中,表中每行爲一個參數(對應URL中的 name=value),注意參數傳入中文時需要勾選“編碼”
 

添加察看結果樹

右鍵點擊“線程組” -> “添加” -> “監聽器” -> “察看結果樹”

這時,我們運行Http請求,修改響應數據格式爲“HTML Source Formatted”,可以看到本次搜索返回結果頁面標題爲”jmeter性能測試_百度搜索“。

添加用戶自定義變量

我們可以添加用戶自定義變量用以Http請求參數化,右鍵點擊“線程組” -> “添加” -> “配置元件” -> “用戶定義的變量”:

新增一個參數wd,存放搜索詞:

並在Http請求中使用該參數,格式爲:${wd}

添加斷言

右鍵點擊“HTTP請求” -> “添加”-> “斷言” -> “響應斷言”

我們校驗返回的文本中是否包含搜索詞,添加參數${wd}到要測試的模式中:

添加斷言結果

右鍵點擊“HTTP請求” -> “添加”-> “監聽器” -> “斷言結果”

這時,我們再運行一次就可以看到斷言結果成功或失敗了

添加聚合報告

右鍵點擊“線程組” -> “添加” -> “監聽器” -> “聚合報告”,用以存放性能測試報告

這樣,我們就完成了一個完整Http接口的JMeter性能測試腳本編寫。

執行性能測試

配置線程組

點擊線程組,配置本次性能測試相關參數:線程數,循環次數,持續時間等,這裏我們配置併發用戶數爲20,持續時間爲60s

執行測試

點擊綠色小箭頭按鈕即可啓動測試,測試之前需要點擊小掃把按鈕清除之前的調試結果。

分析測試報告

聚合報告參數詳解:
1. Label:每個 JMeter 的 element(例如 HTTP Request)都有一個 Name 屬性,這裏顯示的就是 Name 屬性的值
2. #Samples:請求數——表示這次測試中一共發出了多少個請求,如果模擬10個用戶,每個用戶迭代10次,那麼這裏顯示100
3. Average:平均響應時間——默認情況下是單個 Request 的平均響應時間,當使用了 Transaction Controller 時,以Transaction 爲單位顯示平均響應時間
4. Median:中位數,也就是 50% 用戶的響應時間
5. 90% Line:90% 用戶的響應時間
6. Min:最小響應時間
7. Max:最大響應時間
8. Error%:錯誤率——錯誤請求數/請求總數
9. Throughput:吞吐量——默認情況下表示每秒完成的請求數(Request per Second),當使用了 Transaction Controller 時,也可以表示類似 LoadRunner 的 Transaction per Second 數
10. KB/Sec:每秒從服務器端接收到的數據量,相當於LoadRunner中的Throughput/Sec

一般而言,性能測試中我們需要重點關注的數據有: #Samples 請求數,Average 平均響應時間,Min 最小響應時間,Max 最大響應時間,Error% 錯誤率及Throughput 吞吐量。

源碼下載

至此,我們使用JMeter完成了一個完整的Http接口性能測試流程,從腳本編寫,執行到最終結果分析。

完整的腳本源碼下載鏈接: https://pan.baidu.com/s/1eS90cVo 密碼: st15

完整的腳本源碼:

<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="3.2" jmeter="3.3 r1808647">
  <hashTree>
    <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="測試計劃" 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="用戶定義的變量" enabled="true">
        <collectionProp name="Arguments.arguments"/>
      </elementProp>
      <stringProp name="TestPlan.user_define_classpath"></stringProp>
    </TestPlan>
    <hashTree>
      <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="線程組" enabled="true">
        <stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
        <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="循環控制器" enabled="true">
          <boolProp name="LoopController.continue_forever">false</boolProp>
          <intProp name="LoopController.loops">-1</intProp>
        </elementProp>
        <stringProp name="ThreadGroup.num_threads">10</stringProp>
        <stringProp name="ThreadGroup.ramp_time">1</stringProp>
        <longProp name="ThreadGroup.start_time">1509075599000</longProp>
        <longProp name="ThreadGroup.end_time">1509075599000</longProp>
        <boolProp name="ThreadGroup.scheduler">true</boolProp>
        <stringProp name="ThreadGroup.duration">60</stringProp>
        <stringProp name="ThreadGroup.delay"></stringProp>
      </ThreadGroup>
      <hashTree>
        <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP請求" enabled="true">
          <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="用戶定義的變量" enabled="true">
            <collectionProp name="Arguments.arguments">
              <elementProp name="ie" elementType="HTTPArgument">
                <boolProp name="HTTPArgument.always_encode">false</boolProp>
                <stringProp name="Argument.value">utf-8</stringProp>
                <stringProp name="Argument.metadata">=</stringProp>
                <boolProp name="HTTPArgument.use_equals">true</boolProp>
                <stringProp name="Argument.name">ie</stringProp>
              </elementProp>
              <elementProp name="wd" elementType="HTTPArgument">
                <boolProp name="HTTPArgument.always_encode">true</boolProp>
                <stringProp name="Argument.value">${wd}</stringProp>
                <stringProp name="Argument.metadata">=</stringProp>
                <boolProp name="HTTPArgument.use_equals">true</boolProp>
                <stringProp name="Argument.name">wd</stringProp>
              </elementProp>
            </collectionProp>
          </elementProp>
          <stringProp name="HTTPSampler.domain">www.baidu.com</stringProp>
          <stringProp name="HTTPSampler.port"></stringProp>
          <stringProp name="HTTPSampler.protocol">http</stringProp>
          <stringProp name="HTTPSampler.contentEncoding">utf-8</stringProp>
          <stringProp name="HTTPSampler.path">/s</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.embedded_url_re"></stringProp>
          <stringProp name="HTTPSampler.connect_timeout"></stringProp>
          <stringProp name="HTTPSampler.response_timeout"></stringProp>
        </HTTPSamplerProxy>
        <hashTree>
          <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="響應斷言" enabled="true">
            <collectionProp name="Asserion.test_strings">
              <stringProp name="37028633">${wd}</stringProp>
            </collectionProp>
            <stringProp name="Assertion.test_field">Assertion.response_data_as_document</stringProp>
            <boolProp name="Assertion.assume_success">false</boolProp>
            <intProp name="Assertion.test_type">2</intProp>
          </ResponseAssertion>
          <hashTree/>
          <ResultCollector guiclass="AssertionVisualizer" testclass="ResultCollector" testname="斷言結果" 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>false</xml>
                <fieldNames>true</fieldNames>
                <responseHeaders>false</responseHeaders>
                <requestHeaders>false</requestHeaders>
                <responseDataOnError>false</responseDataOnError>
                <saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
                <assertionsResultsToSave>0</assertionsResultsToSave>
                <bytes>true</bytes>
                <sentBytes>true</sentBytes>
                <threadCounts>true</threadCounts>
                <idleTime>true</idleTime>
                <connectTime>true</connectTime>
              </value>
            </objProp>
            <stringProp name="filename"></stringProp>
          </ResultCollector>
          <hashTree/>
        </hashTree>
        <ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="察看結果樹" 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>false</xml>
              <fieldNames>true</fieldNames>
              <responseHeaders>false</responseHeaders>
              <requestHeaders>false</requestHeaders>
              <responseDataOnError>false</responseDataOnError>
              <saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
              <assertionsResultsToSave>0</assertionsResultsToSave>
              <bytes>true</bytes>
              <sentBytes>true</sentBytes>
              <threadCounts>true</threadCounts>
              <idleTime>true</idleTime>
              <connectTime>true</connectTime>
            </value>
          </objProp>
          <stringProp name="filename"></stringProp>
        </ResultCollector>
        <hashTree/>
        <Arguments guiclass="ArgumentsPanel" testclass="Arguments" testname="用戶定義的變量" enabled="true">
          <collectionProp name="Arguments.arguments">
            <elementProp name="wd" elementType="Argument">
              <stringProp name="Argument.name">wd</stringProp>
              <stringProp name="Argument.value">jmeter性能測試</stringProp>
              <stringProp name="Argument.desc">搜索詞</stringProp>
              <stringProp name="Argument.metadata">=</stringProp>
            </elementProp>
          </collectionProp>
        </Arguments>
        <hashTree/>
        <ResultCollector guiclass="StatVisualizer" testclass="ResultCollector" testname="聚合報告" 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>false</xml>
              <fieldNames>true</fieldNames>
              <responseHeaders>false</responseHeaders>
              <requestHeaders>false</requestHeaders>
              <responseDataOnError>false</responseDataOnError>
              <saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
              <assertionsResultsToSave>0</assertionsResultsToSave>
              <bytes>true</bytes>
              <sentBytes>true</sentBytes>
              <threadCounts>true</threadCounts>
              <idleTime>true</idleTime>
              <connectTime>true</connectTime>
            </value>
          </objProp>
          <stringProp name="filename"></stringProp>
        </ResultCollector>
        <hashTree/>
      </hashTree>
    </hashTree>
    <WorkBench guiclass="WorkBenchGui" testclass="WorkBench" testname="工作臺" enabled="true">
      <boolProp name="WorkBench.save">true</boolProp>
    </WorkBench>
    <hashTree/>
  </hashTree>
</jmeterTestPlan>

 

 

jmeter5.0漢化(修改配置即可)

打開apache-jmeter-5.0\bin\jmeter.properties 文件

修改第三十七行,去掉前面的#,

改爲language=zh_CN

重新打開就是中文界面了

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章