Wprowadzenie
Sposób tworzenia aplikacji webowych zmienia się na przestrzeni czasu. W świecie .NET przez lata kodowaliśmy w ASP.NET MVC, w którym widoki były generowane po stronie serwera. Od jakiegoś czasu idziemy w kierunku, w którym backend udostępnia API, z którego korzysta aplikacja po stronie przeglądarki i która generuje widoki po stronie klienta. W związku z tym zmienił się też sposób testowania aplikacji po stronie serwera. Jednym z dostępnych narzędzi, które możemy wykorzystać do testowania API, jest tytułowy Postman. W dzisiejszym wpisie będę chciał Ci przedstawić podstawowe użycie tego świetnego narzędzia.
Postman
Postman jest aplikacją instalowaną w systemie (możemy ją pobrać bezpośrednio z strony https://www.getpostman.com/). Poza Windowsem wspierany jest również Linux oraz Mac. Po zainstalowaniu podczas pierwszego uruchomienia musimy utworzyć konto lub zalogować się z wykorzystaniem konta Google’a. Dzięki temu zapisane żądania będą synchronizowane między komputerami.
Narzędzie udostępnia bardzo dużo przydatnych funkcjonalności. Od podstawowego wysyłania żądań do API, możliwości ich zapisywania do późniejszego użycia i udostępniania ich innym osobom z zespołu, przez tworzenie testów naszego API (możemy pisać asserty dla wyników działania API), po tworzenie mockupów API, które możemy wykorzystać podczas tworzenia frontendu, gdy jeszcze nie mamy właściwej implementacji API.
Dostępnych opcji jest wiele. W tym wpisie skupię się na tych najczęściej używanych, a z czasem, w następnych wpisach, będę pokazywał kolejne ciekawe funkcje.
Zanim przejdę do omawiania Postmana, warto jeszcze przejrzeć Web API, które przygotowałem do testów (dostępne na githubie: https://github.com/danielplawgo/PostmanDemo). Jest to prosty projekt składający się z jednej klasy modelu oraz kontrolera, który udostępnia standardowe akcje (dane są przechowywane w pamięci i generowane przez bibliotekę Bogus).
Kod modelu i kontrolera:
public class Product | |
{ | |
public int Id { get; set; } | |
public string Name { get; set; } | |
public string Category { get; set; } | |
public decimal Price { get; set; } | |
} |
public class ProductsController : ApiController | |
{ | |
private static List<Product> _products; | |
static ProductsController() | |
{ | |
int id = 1; | |
_products = new Faker<Product>() | |
.RuleFor(o => o.Id, f => id++) | |
.RuleFor(p => p.Name, (f, p) => f.Commerce.ProductName()) | |
.RuleFor(p => p.Category, (f, p) => f.Commerce.Categories(1).FirstOrDefault()) | |
.RuleFor(p => p.Price, (f, p) => f.Random.Number(100, 100000) / 100M) | |
.Generate(10); | |
} | |
public IEnumerable<Product> Get() | |
{ | |
return _products; | |
} | |
public Product Get(int id) | |
{ | |
return _products.FirstOrDefault(p => p.Id == id); | |
} | |
public Product Post([FromBody]Product product) | |
{ | |
product.Id = _products.Select(p => p.Id).Max() + 1; | |
_products.Add(product); | |
return product; | |
} | |
public Product Put(int id, [FromBody]Product product) | |
{ | |
var existingProduct = _products.FirstOrDefault(p => p.Id == id); | |
if (existingProduct != null) | |
{ | |
existingProduct.Category = product.Category; | |
existingProduct.Name = product.Name; | |
existingProduct.Price = product.Price; | |
} | |
return existingProduct; | |
} | |
public void Delete(int id) | |
{ | |
var product = _products.FirstOrDefault(p => p.Id == id); | |
if (product != null) | |
{ | |
_products.Remove(product); | |
} | |
} | |
} |
Testowe API nie jest skomplikowane, ale wystarczy nam do przetestowania Postmana. W przykładzie w tym momencie pomijam kwestie związane z uwierzytelnianiem. Oczywiście Postman wspiera praktycznie wszystkie sposoby uwierzytelniania.
Wysyłanie żądań
Postman służy przede wszystkim do wysyłania żądań. Poniżej znajduje się zrzut ekranu z aplikacji z zaznaczonymi najważniejszymi elementami. W aplikacji została wykonana akcja Get testowego kontrolera (http://localhost:60263/api/products), która zwraca listę wszystkich produktów.
Po uruchomieniu Postmana i dodaniu nowego żądania za pomocą przycisku New (lewy górnym róg), za pomocą paska oznaczonego numerem 1 na zrzucie, możemy określić adres (http://localhost:60263/api/products), pod który zostanie wysłane żądanie. Rozwijane menu z punktu 2 umożliwia nam wybranie typu żądania (np. GET, POST, PUT, DELETE):
W przypadku, gdy podczas wysyłania żądania chcemy przekazać jakieś dane do API (np. ustawić parametr w adresie URL, ustawić jakiś nagłówek, czy przekazać jsona wysłanego do usługi), możemy to zrobić za pomocą sekcji pod paskiem z adresem (punkt 3).
Niebieski przycisk Send (punkt 4) wysyła żądanie pod wskazany adres. Po wysłaniu danych i otrzymaniu odpowiedzi widzimy ją w dolnej części aplikacji. W miejscu oznaczonym punktem 5 znajdują się podstawowe statystyki i informacje, na przykład status odpowiedzi (na zrzucie 200 określa, że wszystko wykonało się poprawnie), czas trwania akcji czy rozmiar odpowiedzi.
Obok, w poszczególnych zakładkach (punkt 6), możemy przejrzeć poszczególne elementy odpowiedzi. W zakładce Body widzimy treść odpowiedzi (w przykładzie jest to json zwrócony przez API), nagłówki czy ustawione pliki cookie.
Z lewej strony okna (punkt 7) widzimy dwie zakładki. W History mamy listę wszystkich żądań, który wykonaliśmy. W Collections widzimy natomiast zapisane żądania (o tej zakładce napiszę trochę więcej w dalszej części wpisu).
Środowiska
Jedną z ciekawszych funkcji Postmana, z której warto od razu korzystać, są środowiska. Dzięki niej możemy w bardzo łatwy sposób używać ponownie zapisanych żądań do różnych instancji naszej usługi (np. developerskiej, testowej czy produkcyjnej).
W prawym górnym rogu (punkt 1 na zrzucie ekranu powyżej) znajduje się rozwijana lista, w której możemy wybrać aktualne środowisko, w ramach którego będziemy wykonywać żądania. Jak za chwilkę zobaczysz, w obrębie środowiska możemy definiować zmienne (np. adres naszej usługi), które następnie wykorzystamy w żądaniach. Dla każdego środowiska możemy mieć różne wartości tej samej zmiennej. Dzięki temu przełączenie się między środowiskami może spowodować, że żądanie zostanie wysłane do innej instancji usługi (np. zamiast do lokalnej wersji developerskiej dane są wysyłane do wersji na serwerze testowym). I to wszystko bez konieczności modyfikowania samego żądania.
Za pomocą przycisku z punktu 2 możemy podejrzeć konfigurację aktualnie wybranego środowiska (głównie listę zmienny oraz ich wartości) oraz przejść do widoku edycji wybranego środowiska (okno z powyższego zrzutu ekranu).
W oknie edycji poza zmianą nazwy środowiska (punkt 3) definiujemy przede wszystkim zmienne i ich wartości (punkt 4). Przy definiowaniu zmiennej określamy trzy wartości: nazwę (kolumna Variable), domyślną wartość (kolumna Initial Value) oraz wartość aktualną (kolumna Current Value). Warto zaznaczyć różnicę między dwiema ostatnimi kolumnami. Wartość domyślna to wartość, która później będzie zapisywana w kolekcji i synchronizowana (czyli udostępniana innym osobom). Wartość aktualna zaś to wartość, która faktycznie zostanie wysłana i jest przechowywana tylko lokalnie. Dzięki temu w niej możemy przechowywać dane wrażliwe (np. login, hasło czy tokeny potrzebne do uwierzytelniania) i te, które nie powinny zostać udostępnione innym.
Aby używać zmiennej, wystarczy w treści żądania (np. w adresie lub w parametrze) skorzystać z nazwy zmiennej otoczonej podwójnymi nawiasami {{nazwa zmiennej}}, np. {{url}}. Widać to na poniższym zrzucie, gdzie zmienna url została użyta w adresie:
Kolekcje
Ostatnim elementem, który chcę omówić w tym wpisie, są kolekcje. Wykonane żądanie możemy zapisać w kolekcji do ponownego wykorzystywania. Samą kolekcję możemy później współdzielić lub wyeksportować do repozytorium.
Z prawej strony okna Postmana mamy listę kolekcji. Możemy dodawać nowe i następnie do nich zapisywać żądania. Samo żądanie zapisujemy przyciskiem Save obok przycisku Send:
Określamy nazwę żądania (punkt 1), możemy ustawić opis (punkt 2), a na końcu wybieramy kolekcję, do której chcemy zapisać żądanie. W ramach kolekcji możemy tworzyć foldery, aby ładniej pogrupować zapisane żądania.
Mając już kolekcję z żądaniami, możemy ją współdzielić (punkt 1 poniżej) lub wyeksportować (punkt 2). W darmowej wersji możemy współdzielić do 25 żądań (bez znaczenia, ile osób mamy w projekcie). Gdy potrzebujemy więcej, możemy skorzystać z jednego z dostępnych płatnych planów.
W przypadku eksportu możemy plik jsona z żądaniami wrzucić do repozytorium i w ten sposób współdzielić żądania w zespole. Przykład takiej wyeksportowanej kolekcji znajdziesz na moich githubie (https://github.com/danielplawgo/PostmanDemo/blob/master/Tests/Blog.postman_collection.json). Są to przykładowe żądania do testowego API.
Przykład
Na githubie (https://github.com/danielplawgo/PostmanDemo) znajduje się przykład, którego użyłem do testów Postmana. W repozytorium znajduje się wyeksportowana kolekcja, którą możesz zaimportować i samemu przetestować Postmana.
Podsumowanie
Postman jest bardzo przydatnym narzędziem, którego możemy użyć podczas pracy nad API. Udostępnia on szereg funkcjonalności, które ułatwiają oraz przyśpieszają proces testowania API. W tym wpisie pokazałem Ci kilka podstawowych funkcjonalności. Z czasem postaram się opisać również kilka bardziej rozbudowanych opcji, których możesz używać w swojej pracy.
A Ty jakiego narzędzia używasz do testowania API?
Swietny artykul. Dzieki bardzo 🙂
Dzięki!
Postman jest też o tyle wygodny że można automatycznie generować tokeny OAuth2. Pisałem o tym kiedyś, dla zainteresowanych (en): https://marcin-chwedczuk.github.io/automatically-generate-new-oauth2-tokens-when-using-postman