Planowanie testów obciążeniowych przy użyciu narzędzia Apache JMeter

Ukończone

W tej sekcji zapoznasz się z testowaniem obciążenia i dowiesz się, jak dodać testy obciążeniowe do potoku. Testy obciążeniowe używają narzędzia Apache JMeter do symulowania wielu użytkowników, którzy uzyskują jednocześnie dostęp do aplikacji internetowej. Testy pobierają zawartość internetową z aplikacji działającej w usłudze aplikacja systemu Azure w środowisku przejściowym.

Tim rozpoczyna się od uruchomienia interfejsu użytkownika Apache JMeter na laptopie. Prowadzi podstawowy plan testowy. Następnie Tim i Mara wyeksportuj plan testowy do pliku, który można uruchomić z wiersza polecenia. Na koniec dodają zadania do usługi Azure Pipelines, aby uruchamiać testy obciążeniowe podczas przemieszczania.

Uwaga

W przypadku zwięzłości nie trzeba instalować narzędzia Apache JMeter na komputerze lokalnym. Możesz po prostu przeczytać.

Uruchamianie testów obciążeniowych z narzędzia Apache JMeter

Apache JMeter to narzędzie do testowania obciążenia typu open source, które analizuje i mierzy wydajność. Wygenerowany raport jest plikiem XML.

Usługa Azure Pipelines może odczytać raport Apache JMeter i wygenerować graf. Nie potrzebujesz żadnego specjalnego sprzętu do uruchamiania tych testów, aby można było uruchomić je za pomocą agenta hostowanego przez firmę Microsoft. W scenariuszu Space Game prawdopodobnie uruchomisz te testy w środowisku przejściowym.

Tworzenie planu testu

Oto jak wygląda narzędzie Apache JMeter na laptopie z systemem Linux:

Screenshot of the Apache JMeter user interface.

Utworzysz nowy plik planu testu; na przykład LoadTest.jmx. Następnie należy dodać grupę wątków do pliku. Każdy symulowany użytkownik działa we własnym wątku. Grupa wątków kontroluje liczbę użytkowników i liczbę żądań każdego użytkownika.

W poniższym przykładzie pokazano 10 symulowanych użytkowników (wątków). Każdy użytkownik wysyła 10 żądań, więc system otrzymuje łącznie 100 żądań.

Screenshot of specifying the thread group in Apache JMeter.

Przykładomierz jest pojedynczym żądaniem wykonanym przez JMeter. JMeter może wysyłać zapytania do serwerów za pośrednictwem protokołu HTTP, FTP, TCP i kilku innych protokołów. Próbkatory generują wyniki dodane do raportu.

Następnie do grupy wątków dodasz wartości domyślne żądania HTTP i przykładowy moduł żądania HTTP. Należy podać nazwę hosta witryny internetowej Space Game, która działa w środowisku przejściowym w usłudze aplikacja systemu Azure Service.

Screenshot that shows specifying the HTTP request in Apache JMeter.

Powyższy scenariusz tworzy podstawowy plan testu.

Uruchamianie planu testu

JMeter umożliwia uruchamianie wielu rodzajów testów. Można uruchomić plan testu z graficznego interfejsu użytkownika narzędzia JMeter. Jednak w przypadku testów obciążeniowych dokumentacja narzędzia JMeter zaleca uruchomienie planu testu z poziomu wiersza polecenia.

Plan testów należy uruchomić przy użyciu tego polecenia:

apache-jmeter-5.4.1/bin/./jmeter -n -t LoadTest.jmx -o Results.xml

Argument -n określa, aby uruchomić JMeter w trybie innego niż GUI. Argument -t określa plik planu testu LoadTest.jmx. Argument -o określa plik raportu, Results.xml.

Narzędzie JMeter uruchamia i generuje plik raportu, Results.xml. W tym przykładzie pliku przedstawiono kilka pierwszych wyników:

<?xml version="1.0" encoding="UTF-8"?>
<testResults version="1.2">
<httpSample t="180" it="0" lt="95" ct="35" ts="1569306009772" s="true" lb="HTTP Request" rc="200" rm="OK" tn="Thread Group 1-1" dt="text" by="40871" sby="144" ng="1" na="1">
  <java.net.URL>http://tailspin-space-game-web-staging-1234.azurewebsites.net/</java.net.URL>
</httpSample>
<httpSample t="174" it="0" lt="96" ct="38" ts="1569306009955" s="true" lb="HTTP Request" rc="200" rm="OK" tn="Thread Group 1-1" dt="text" by="40869" sby="144" ng="1" na="1">
  <java.net.URL>http://tailspin-space-game-web-staging-1234.azurewebsites.net/</java.net.URL>
</httpSample>
<httpSample t="160" it="0" lt="121" ct="35" ts="1569306010131" s="true" lb="HTTP Request" rc="200" rm="OK" tn="Thread Group 1-1" dt="text" by="40879" sby="144" ng="2" na="2">
  <java.net.URL>http://tailspin-space-game-web-staging-1234.azurewebsites.net/</java.net.URL>
</httpSample>

Każdy przykład tworzy węzeł w raporcie. Atrybut t określa czas odpowiedzi w milisekundach (ms). W tym miejscu zobaczysz trzy żądania, które miały 180 ms, 174 ms i 160 ms.

Idealne czasy żądań powinny wynosić średnio mniej niż jedną sekundę. Nie więcej niż 10 procent żądań powinno potrwać więcej niż jedną sekundę. Możesz skonfigurować parametr JMeter w celu raportowania statystyk, takich jak minimalny, maksymalny i średni czas odpowiedzi lub odchylenie standardowe. Możesz napisać skrypt, aby pomóc w podaniu tych informacji.

Aby zwizualizować wyniki testu, należy podać je w formacie zrozumiałym dla usługi Azure Pipelines. Usługa Azure Pipelines może przeanalizować plik XML zawierający wyniki testu, ale plik musi być w obsługiwanym formacie. Obsługiwane formaty to CTest, JUnit (w tym PHPUnit), NUnit 2, NUnit 3, Visual Studio Test (TRX) i xUnit 2. Możesz napisać plik XSLT, który konwertuje wyniki JMeter na JUnit.

Przekształcanie raportu w JUnit

XSLT oznacza przekształcenia XSL lub eXtensible Stylesheet Language Transformations. Plik XSLT przypomina plik XML, ale umożliwia przekształcenie dokumentu XML w inny format XML.

Przypomnij sobie nasze wymagania dotyczące testów obciążeniowych:

  • Średni czas żądania powinien być krótszy niż jedna sekunda.
  • Nie więcej niż 10 procent żądań powinno potrwać więcej niż jedną sekundę.

Oto jak wygląda plik XSLT spełniający te wymagania:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:math="http://exslt.org/math">
  <xsl:output method="xml" indent="yes" encoding="UTF-8"/>
  <xsl:template match="/testResults">
    <xsl:variable name="times" select="./httpSample/@t" />
    <xsl:variable name="failures" select="./httpSample/assertionResult/failureMessage" />
    <xsl:variable name="threshold" select="1000" />
    <testsuite>
      <xsl:attribute name="tests"><xsl:value-of select="count($times)" /></xsl:attribute>
      <xsl:attribute name="failures"><xsl:value-of select="count($failures)" /></xsl:attribute> 
      <testcase>
          <xsl:variable name="avg-time" select="sum($times) div count($times)" />
          <xsl:attribute name="name">Average Response Time</xsl:attribute>
          <xsl:attribute name="time"><xsl:value-of select="format-number($avg-time div 1000,'#.##')"/></xsl:attribute>
          <xsl:if test="$avg-time > $threshold">
            <failure>Average response time of <xsl:value-of select="format-number($avg-time,'#.##')"/> exceeds <xsl:value-of select="$threshold"/> ms threshold.</failure>
          </xsl:if> 
      </testcase>
      <testcase>
          <xsl:variable name="exceeds-threshold" select="count($times[. > $threshold])" />
          <xsl:attribute name="name">Max Response Time</xsl:attribute>
          <xsl:attribute name="time"><xsl:value-of select="math:max($times) div 1000"/></xsl:attribute>
          <xsl:if test="$exceeds-threshold > count($times) * 0.1">
            <failure><xsl:value-of select="format-number($exceeds-threshold div count($times) * 100,'#.##')"/>% of requests exceed <xsl:value-of select="$threshold"/> ms threshold.</failure>
          </xsl:if>
      </testcase>
    </testsuite>
  </xsl:template>
</xsl:stylesheet>

Nie zagłębimy się w sposób działania XSL tutaj. Jednak podsumowując, ten plik najpierw zbiera następujące dane z danych wyjściowych JMeter:

  • Każdy czas żądania HTTP.

    Zbiera te dane, wybierając t atrybut z każdego httpSample elementu. (./httpSample/@t)

  • Każdy komunikat o błędzie.

    Zbiera te dane, wybierając wszystkie failureMessage węzły z dokumentu. (./httpSample/assertionResult/failureMessage)

Plik XSLT ustawia również wartość progową na 1000 ms. Ten czas odpowiedzi to maksymalna wartość zdefiniowana wcześniej.

Biorąc pod uwagę te zmienne, plik XSLT zawiera łączną liczbę testów i łączną liczbę niepowodzeń. Następnie udostępnia te dwa przypadki testowe:

  • Średni czas odpowiedzi i błąd, jeśli średnia przekracza próg 1000 ms.
  • Maksymalny czas odpowiedzi i błąd, jeśli ponad 10 procent żądań przekroczy próg 1000 ms.

Wyniki XSLT są zgodne z formatem JUnit, który rozumie usługa Azure Pipelines. Możesz nazwać plik XSLT JMeter2JUnit.xsl.

Następnie potrzebny będzie procesor XSLT. W tym przykładzie użyjemy xsltproc, czyli narzędzia wiersza polecenia do stosowania arkuszy stylów XSLT do dokumentów XML.

Możesz zainstalować plik xsltproc w następujący sposób:

sudo apt-get install xsltproc

Następnie uruchomisz polecenie xsltproc , aby przekształcić raport JMeter na JUnit:

xsltproc JMeter2JUnit.xsl Results.xml > JUnit.xml

Oto wynikowy plik JUnit, JUnit.xml:

<?xml version="1.0" encoding="UTF-8"?>
<testsuite xmlns:math="http://exslt.org/math" tests="100" failures="0">
  <testcase name="Average Response Time" time="0.17"/>
  <testcase name="Max Response Time" time="0.373"/>
</testsuite>

W tym przykładzie średni czas odpowiedzi wynosi 170 ms. Maksymalny czas odpowiedzi to 373 ms. Żaden przypadek testowy nie generuje błędu, ponieważ oba razy spadną poniżej progu 1000 ms.

Wkrótce uruchomisz te testy w potoku. Możesz pomyśleć o Results.xml pliku, który zapisuje JMeter, jako plik pośredni, który nie jest publikowany w wynikach testu potoku. JUnit.xml jest ostatnim plikiem raportu. Ten plik zostanie opublikowany w potoku, aby zespół mógł wizualizować wyniki.