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

Ukończone

W tej sekcji zapoznasz się z testowaniem wydajnościowym i dowiesz się, jak dodać testy wydajnościowe do procesu. 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 Azure App Service w przejściowym środowisku .

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ć za pomocą wiersza polecenia. Na koniec dodają zadania do usługi Azure Pipelines, aby uruchamiać testy obciążeniowe podczas etapu przygotowawczego.

Notatka

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:

zrzut ekranu interfejsu użytkownika apache JMeter.

Utworzysz nowy plik planu testu; na przykład LoadTest.jmx. Następnie dodasz do pliku grupę wątków . 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ń.

Zrzut ekranu przedstawiający określanie grupy wątków w narzędziu Apache JMeter.

Próbka to pojedyncze żądanie wykonane 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, które są dodawane do raportu.

Następnie do grupy wątków dodasz wartości domyślne żądań HTTP i próbkę żądania HTTP. Należy podać nazwę hosta witryny internetowej Space Game uruchomionej w środowisku przejściowym w usłudze Azure App Service.

Zrzut ekranu przedstawiający określanie żądania HTTP w narzędziu 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 niezwiązanym z graficznym interfejsem użytkownika. Argument -t określa plik planu testu, LoadTest.jmx. Argument -o określa plik raportu, Results.xml.

Narzędzie JMeter uruchamia i tworzy 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żda próbka 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 Transformacje 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:

  • Czas każdego żądania HTTP.

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

  • Każdy komunikat o błędzie.

    Zbiera te dane, wybierając wszystkie węzły failureMessage 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, który jest narzędziem wiersza polecenia do stosowania arkuszy stylów XSLT do dokumentów XML.

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

sudo apt-get install xsltproc

Następnie uruchomisz 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ż czasy obu przypadków spadają poniżej progu czasowego 1 000 ms.

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