Skip to content

wojciech11/se_http_api_testing_quickstart

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 

Repository files navigation

Praca z API HTTP w pigułce

Warto wiedzieć:

  • Kody HTTP, minimum znać, patrz na MDN web docs:

    • Successful responses - 2xx: 200, 201,
    • Redirects - 3xx: 301, 302,
    • Client errors - 4xx: 400, 401, 403, 404, 405, 422, 429,
    • Server errors - 5xx: 500, 502, 503 i 504.
  • Metody HTTP, podstawowe (więcej na MDN):

    • POST,
    • GET,
    • PUT,
    • DELETE.
  • Co to jest REST / REST API? Jakie zasady powinno spełniać API? Na pewno bym zaczął od:

    • poleganie na HTTP w sposobie działania,
    • bezstanowość - każdy request zawiera całą informację o stanie,
    • ścieżka, semantyczna/logiczna z nazwą zasobu, np: companies/1/employees/2.
  • [Dodatkowe] Przeczytaj co to jest GraphQL.

Praca z API

  • Curl & httpie - szybkie sprawdzenie lub proste skrypty w bashu (czasami można się pokusić o proste checki z pomocą Bats-core):

    $ curl -X POST -H "Content-Type: application/json" \
         -d '{"name":"natalia"}' https://httpbin.org/post
    
    $ http POST  https://httpbin.org/post "name"="natalia"
    # szybki smoke test
    
    $ curl -X GET https://httpbin.org/status/404 --fail
    # --fail, dzięki temu zwraca curl błąd
    $ echo $?
    
    # mamy teraz endpoint oczekujący get, a wysyłamy POST:
    $ curl -X POST https://httpbin.org/get --fail
    
    # porównaj z:
    $ curl -X GET https://httpbin.org/get --fail
    $ curl -X GET https://httpbin.org/status/404 --fail
    $ export API_ENDPOINT=127.0.0.1:5000
    $ curl -s -o /dev/null -w "%{http_code}" --fail ${API_ENDPOINT}

    A jak w skrypcie (zauważ z httpie byłoby zdecydowanie prościej :) ):

    # chcemy wyciąnąć imie z odpowiedzi na naszego POST
    $ curl -s --fail -X POST -H "Content-Type: application/json" \
        -d '{"name":"natalia"}' https://httpbin.org/post
    
    $ curl -s --fail -X POST -H "Content-Type: application/json" \
        -d '{"name":"natalia"}' https://httpbin.org/post \
        | jq '.json | .name'
    
    $ curl -s --fail -X POST -H "Content-Type: application/json" \
        -d '{"name":"natalia"}' https://httpbin.org/post \
        | jq '.json | .name' | tr -d '"'

    Teraz skrypt, show_name.bash (skąd te flagi? Przeczytaj better bash in 15 minutes):

    #!/bin/bash
    set -o nounset
    set -o errexit
    set -o pipefail
    
    GENERATED_NAME=$(curl -s --fail -X POST -H "Content-Type: application/json" -d '{"name":"natalia"}' https://httpbin.org/post | jq '.json | .name' | tr -d '"  ')
    
    if [[ $GENERATED_NAME != "natalia" ]]; then
        echo "bledna wartosc: ${GENERATED_NAME}"
        exit 1
    else
      echo "OK"
    fi
  • Praca z API, przygotowując skrypt wykorzystujący API jeśli popełniasz błędy zazwyczaj natkniesz się na następujące błędy:

    • 400
    • 422 - serwer przyjął twoje żądanie ale serwer nie jest w stanie pracować z danymi, które właśnie przesłałaś
    • 404
    • 403
    • 405 - method not allowed, próbujemy POST na endpoint-cie (ścieżce API) zamiast GET

    Zauważ, czasami możesz mieć problemy z rate-limiting, w zależności od API dostaniesz różne odpowiedz, patrz rate limit Github z 403 i porównaj do Stripe rate limiting posługującym się 429

  • biblioteka requests (bread & butter):

    import requests
    
    # pamietaj o timeout
    srv = "https://services.odata.org/v4/TripPinServiceRW/People('russellwhyte')"
    result = requests.get(srv)
    
    # moglibyśmy przerwać żądanie
    # result.raise_for_status()
    
    print("Status: {0}".format(result.status_code))
    print("Result: {0}".format(result.json()))
  • unittesty flask - patrz twoje testy w test_views.py na podstawie test_views w projekcie do ćwiczeń

    • sprawdź czy status_code jest jaki oczekujesz;

    • zawsze parsujemy wynik za pomocą odpowiedniej biblioteki, np., json czy lxml;

    • jeśli JSON to kapitalnie sprawdza się również biblioteka jmespath (jak XPATH ale dla JSONA!), np:

      import jmespath
      import requests
      
      r = requests.get("http://127.0.0.1:5000?output=json")
      rj = r.json()
      
      expected = "Apolonia"
      actual = jmespath.search("imie", rj)
      if actual != expected:
          print("aaa!")
  • requests i behave lub Robot - dla czytelności naszych intencji możemy wykorzystać BDD do lepszego opisania naszych testów, patrz instrukcja Python część 2 z BDD.

  • postman lub insomnia - manualne testy, większość firm w których pracowałem wykorzystywały to do manualnego testowania i współdzielenie know-how jak korzystać z danych endpointów. Warto zacząć skupić się na building requests, można szybko również spojrzeć na pozostałe tematy w ich tutorialu.

  • zewnętrzne serwisy mogą być wolne lub możemy mieć problemy z połączeniem z nimi, więc warto zawsze określać timeouty, gdy wykonujemy zewnętrze requesty (patrz requests timeouts):

    requests.get('https://github.com/', timeout=0.001)
  • Pamiętaj, że mamy wiele rodzajów API oraz metod RFC (remote function call) dla wywołania zdalnej funkcjonalności zdania przez, np., protokół HTTP lub inny.

Dodatkowe

About

W pigułce, co należy wiedzieć, aby testować API

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published