Sprawdzone metody testowania

Opracowanie obiektu Action for the Actions on Google często obejmuje implementację Dialogflow do rozumienia języka naturalnego (NLU) i realizacji Dialogflow, która obsługuje logikę działania. Testy w bazie kodu pomagają zapewnić, że akcja będzie działać zgodnie z oczekiwaniami w środowisku produkcyjnym.

Implementując jednostkowe testy integracji lub kompleksowe testy na potrzeby akcji, należy traktować agenta Dialogflow i realizację jako osobne komponenty.

Schemat blokowy przechodzi od zapytania użytkownika do Actions on Google, Dialogflow i webhooka realizacji, a potem wraca do użytkownika.

Rysunek 1. Schemat blokowy opisujący systemy do przetestowania

Testowanie agenta Dialogflow

Agent Dialogflow i realizacja są testowane jako osobne komponenty. Poniżej znajdziesz opis sposobu opracowywania i testowania agenta Dialogflow w przypadku akcji.

Dialogflow jako system wysyłania zapytań i wycofywania intencji

Agent Dialogflow jest odpowiedzialny za przyjęcie zapytania użytkownika, dopasowanie go do intencji i wyodrębnienie z niego wszelkich wstępnie zdefiniowanych encji. Agent wchodzi w interakcję z realizacją, przekazując wiadomość zawierającą odpowiedni zamiar, jego parametry i metadane Actions on Google.

Jako programista kontrolujesz konfigurację agenta Dialogflow, w tym strukturę intencji i encji. Metadane w Actions on Google pochodzą z Actions on Google i można założyć, że zawierają one prawidłowe dane do testów.

Podczas testowania skup się na tym, aby agent mógł prawidłowo wyodrębniać parametry intencji i dopasowywać zapytania do intencji. Takie podejście zapewnia wymierne dane do oceny wydajności agenta. Aby obliczyć ten wskaźnik, możesz przygotować i wykorzystać poszczególne przypadki testowe lub zbiór do weryfikacji.

Agenta Dialogflow można reprezentować za pomocą zapytania tekstowego jako danych wejściowych i zamiaru oraz wyodrębnionych parametrów intencji jako danych wyjściowych.

Rysunek 2. Prezentowanie Dialogflow jako systemu rozpoczynającego zapytanie i przekazywania intencji

Testy jednostkowe

W przypadku agenta Dialogflow możesz tworzyć testy, w których każdy przypadek wymaga podania zapytania tekstowego i wygeneruje metadane intencji. Te metadane powinny zawierać (co najmniej) nazwę dopasowanej intencji i listę pasujących parametrów.

Punkt końcowy detectIntent interfejsu Dialogflow API przyjmuje zapytanie tekstowe jako dane wejściowe i tworzy uporządkowane dane wyjściowe zawierające nazwę rozpoznanej intencji i wyodrębnionych parametrów. Dane wyjściowe przydają się do oceny skuteczności agenta przez dopasowywanie intencji. Pełne informacje o innych przydatnych polach znajdziesz w dokumentacji usługi QueryResult.

Przykładowy test wygląda tak:

it('choose_fact', async function() {
  // The `dialogflow` variable is an abstraction around the API that creates
  // and sends payloads to Dialogflow.
  const resJson = await dialogflow.detectIntent(
    'Tell me about the history of Google');
  expect(resJson.queryResult).to.include.deep.keys('parameters');
  // Check that Dialogflow extracted required entities from the query.
  expect(resJson.queryResult.parameters).to.deep.equal({
    'category': 'history',
    // Put any other parameters you wish were extracted
  });
  expect(resJson.queryResult.intent.displayName).to.equal('choose_fact');
});

Ten fragment kodu używa Mocha i Chai. W sekcji Fakty o Google zapoznaj się z pełnym przykładem działającego testu jednostkowego Dialogflow napisanego w Node.js.

Twoje pliki testowe możesz uruchamiać równolegle, ponieważ interfejs Dialogflow API akceptuje sessionId jako argument. Dzięki temu można utworzyć oddzielną piaskownicę dla każdej rozmowy, jednocześnie korzystając z pojedynczego klienta Dialogflow API.

Wysyłasz żądania do interfejsu Dialogflow API, więc jeśli osiągniesz limit bezpłatnych wywołań, mogą zostać naliczone opłaty. Więcej informacji znajdziesz w sekcji Limity i limity.

Testy integracji

Punkt końcowy detectIntent interfejsu Dialogflow API aktywuje też realizację zewnętrzną. Można więc tworzyć przypadki testowe, które obejmują integrację między agentem Dialogflow a realizacją Dialogflow.

Główna różnica między pisaniem integracji a testami jednostowymi w Dialogflow polega na tym, że podczas testu integracji możesz potwierdzić, że odpowiedzi pochodzą z webhooka oraz intencji Dialogflow i wyodrębniania encji.

Pełny działający przykład testu integracji napisanego w Node.js znajdziesz w repozytorium Informacje o Google.

Testowanie webhooka realizacji Dialogflow

Agent Dialogflow i realizacja Dialogflow są testowane jako osobne komponenty. W podsekcjach poniżej opisujemy, w jaki sposób możesz rozumieć i testować realizację akcji.

Realizacja jako system JSON-In-JSON-out

Twój kod realizacji Dialogflow oczekuje żądań i generuje odpowiedzi w formacie JSON. Dzięki temu możesz przetestować swój kod realizacji, postrzegając go jako system JSON-In i JSON-out. Żądanie zawiera metadane zarówno z Dialogflow, jak i Actions on Google, dlatego zawiera wszystko, co jest potrzebne do aktywowania określonego modułu obsługi intencji w realizacji.

Aby przetestować aktywowanie modułu obsługi intencji, musisz wysłać do akcji żądanie JSON (wejściowe). Żądanie jest przekazywane do realizacji, która jest dostępna w internecie. Realizacja następnie generuje odpowiedź JSON (dane wyjściowe), którą można ocenić na potrzeby weryfikacji.

Realizację można reprezentować za pomocą danych wejściowych żądania JSON i wyjściowej odpowiedzi JSON webhooka.

Rysunek 3. Prezentacja realizacji jako systemu JSON-In-JSON-out.

Testy jednostkowe

Kod webhooka realizacji transakcji to system, który akceptuje dane wejściowe JSON i generuje dane wyjściowe JSON. Proces testowania akcji jest następnie uproszczony – do przesłania żądania do realizacji i sprawdzenia wyjściowego pliku JSON.

Dzięki temu możesz swobodnie hostować realizację zamówień lokalnie i wysyłać żądania HTTP lokalnie do testów. Jeśli używasz biblioteki klienta Actions on Google Node.js, możesz też wysyłać żądania JSON bezpośrednio do warstwy oprogramowania pośredniczącego biblioteki klienta.

Jeśli przetestujesz kod webhooka z użyciem danych wejściowych JSON i otrzymasz oczekiwane dane wyjściowe JSON, możesz z dużą pewnością stwierdzić, że elementy, które kontrolujesz, działają prawidłowo. Możesz przyjąć, że Dialogflow i Actions on Google działają prawidłowo, ponieważ generują prawidłowe ładunki JSON. Taka izolacja zapewnia uproszczony model programowania do pisania testów.

Oto ogólny zarys procesu testowania:

  1. Użyj symulatora w Konsoli Actions, aby uzyskać żądania JSON dla każdego kroku w danym przypadku użycia. Zapisz je jako pliki JSON. Możesz też utworzyć te żądania samodzielnie, korzystając z informacji z dokumentacji referencyjnej webhooka.
  2. Napisz testy, które będą wywoływać webhooka z tymi ładunkami.
  3. W przypadku każdego testu sprawdź, czy odpowiedź w formacie JSON zawiera oczekiwane elementy.

Dodatkowo ten model umożliwia testowanie realizacji Dialogflow w ramach ustawienia ciągłej integracji, ponieważ punkt końcowy realizacji zamówienia może działać lokalnie, a interfejs Dialogflow API ma wbudowaną koncepcję sesji.

Przykładowy test wygląda tak:

it('yes-history', function() {
  expect(jsonRes.payload).to.have.deep.keys('google');
  expect(jsonRes.payload.google.expectUserResponse).to.be.true;
  expect(jsonRes.payload.google.richResponse.items).to.have.lengthOf(3);
  expect(jsonRes.payload.google.richResponse.suggestions).to.have
    .deep.members([
      {'title': 'Sure'}, {'title': 'No thanks'},
    ]);
});

Powyższy fragment kodu używa elementów Mocha i Chai. Pełen działający przykład napisany w środowisku Node.js znajdziesz w repozytorium Facts About Google (Fakty o Google).

Projektowanie realizacji możliwej do przetestowania jednostek

Kod webhooka często zawiera niestandardową logikę biznesową, na której aplikacja wykorzystuje swoje potrzeby. Dodatkowo kod webhooka może też zawierać moduły obsługi intencji.

Aby zwiększyć szczegółowość testów jednostkowych kodu realizacji, warto uporządkować kod w taki sposób, aby logika biznesowa była oddzielona od procedur obsługi intencji. Oznacza to, że moduły obsługi intencji i logika biznesowa są umieszczone w osobnych modułach, dzięki czemu każdy element może być testowany niezależnie.

Zapoznaj się z naszym przykładowym działaniem shiritori na GitHubie. W tym przykładzie functions/index.js i functions/shiritori/*.js oddzielnie zawierają moduły obsługi intencji i logikę biznesową, co pozwala na utworzenie bardziej rozbudowanych zestawów testów.

Testy integracji

Informacje o przypadkach testowych dotyczących integracji między Dialogflow a kodem webhooka realizacji znajdziesz w sekcji testowania integracji Dialogflow powyżej.

Testy wczytywania

Przed wdrożeniem akcji w środowisku produkcyjnym zalecamy też przetestowanie obciążenia realizacji webhooka, aby wykryć problemy z wydajnością, które powodują pogorszenie lub zakłócenie działania usługi realizacji zamówień.

Oto kilka przykładów problemów z wydajnością, które mogą wystąpić podczas testowania obciążenia:

  • Ograniczona moc obliczeniowa i pamięć
  • Ograniczenia limitów od dostawców
  • Powolny odczyt i zapis danych
  • Problemy z równoczesnością w kodzie

Scenariusze testowania obciążenia zależą od oczekiwanego lub historycznego wzorca użytkowania akcji, ale typowymi scenariuszami do testowania są nagły wzrost obciążenia (wzrost) i długotrwałe obciążenie (napływ).

Określ scenariusze, w których webhook jest wywoływany i wykonuje operacje wymagające znacznych zasobów. Typowe operacje wymagające znacznych zasobów obejmują wysyłanie zapytań do bazy danych, wywoływanie innego interfejsu API, wykonywanie obliczeń oraz wykonywanie operacji wymagających dużej ilości pamięci, takich jak renderowanie pliku dźwiękowego.

W tych przypadkach możesz przechwytywać żądania wysyłane do webhooka przez serwery Actions on Google z dzienników webhooka lub logów usługi Stackdriver. Żądania możesz też przechwytywać w symulatorze konsoli Actions.

Po otrzymaniu żądań możesz użyć narzędzia do testowania obciążenia, aby sprawdzić, jak webhook odpowiada w przypadku różnych scenariuszy testowania obciążenia. W podsekcjach poniżej znajdziesz kilka przykładów testowania skoków i testowania głębokości za pomocą ApacheBench.

Testy wzrostów

Testowanie na dużą skalę wymaga wysyłania do webhooka stałej liczby żądań przez pewien czas i nagłego zwiększenia obciążenia. Możesz np. skonfigurować test, który wysyła obciążenie wynoszące 10 zapytań na sekundę z kilkoma skokami po 60 zapytaniach na sekundę.

Możesz uruchomić to polecenie ApacheBench, aby wysłać do webhooka 60 równoczesnych żądań:

ab -n 60 -c 60 -p ActionRequest.json -T 'application/json' https://example.com/webhookFunctionName

Załóżmy, że plik ActionRequest.json zawiera przechwycony ładunek żądania wysłany do webhooka.

Testy zwilżania

Testowanie oddziaływania wymaga wysyłania do webhooka stałej liczby żądań i obserwowania odpowiedzi. Możesz np. skonfigurować test, który przez kilka minut wysyła stałe obciążenie 10–20 zapytań na sekundę, aby sprawdzić, czy wydłuży się czas odpowiedzi.

Możesz uruchomić to polecenie ApacheBench, aby wysłać 1200 żądań z 10 żądaniami równoczesnymi na sekundę:

ab -t 120 -n 1200 -p ActionRequest.json -T 'application/json' https://example.com/webhookFunctionName

Załóżmy, że plik ActionRequest.json zawiera przechwycony ładunek żądania wysłany do webhooka.

Analizuję wyniki testowania obciążenia

Po przeprowadzeniu testów obciążenia przeanalizuj wyniki czasu odpowiedzi webhooka. Wskaźnikami problemów z implementacją webhooka są zwykle trendy, takie jak mediana czasu odpowiedzi, który zwiększa się z każdym testem, lub czas odpowiedzi w najgorszym przypadku, który jest niedopuszczalny w przypadku danego działania.

Kompleksowe testowanie

Pełne testowanie przed przesłaniem akcji do zatwierdzenia odbywa się za pomocą symulatora Konsoli Actions. Instrukcje kompleksowego testowania znajdziesz w symulatorze Konsoli Actions w dokumentacji Symulatora Actions. Przeprowadzanie tych testów pomaga eliminować potencjalne niepewności dotyczące komponentu infrastruktury Actions on Google.