De standaardclient en statusklassen · eindproject
Eindproject: Project: een client met de standaardbibliotheek
get_json, classify en report werken, en je hebt ze scenario voor scenario tegen practice-api zien werken. Een uitvoering tegen een live dienst laat zien dat één geval één keer werkte. Tests op een vervangende verbinding laten meer zien: elke klasse, de foutbodies, een time-out en het sluiten, elke keer dat je ze uitvoert, zonder dat er een server nodig is. Dit project maakt de client af en bewijst hem met je eigen tests.
Wat de client belooft
Als dit project klaar is, houdt wire.py zich aan deze beloften, en je tests controleren ze:
get_jsongeeft het volledige record terug voor een antwoord van elke klasse:"status","reason","headers","content_type","retry_after","body","class"en"data".De body van elke 4xx en 5xx wordt bewaard, en gedecodeerd in
"data"als hij alsgelabeld is. Als er geen antwoord aankomt, verlaat
TimeoutErrorget_json, en is de verbinding gesloten.reportmaakt van een time-out een regel die geen status noemt, en laat elke andere mislukking door.
Als een van deze beloften nog niet klopt, herstel dat dan eerst. Als les 1 tot en met 5 allemaal geslaagd zijn, hoeft je code misschien niet te veranderen.
De twee fakes
Open fakes.py en lees de twee fake_connect. scripted_response(status, reason, header_pairs, body) bouwt een antwoord: header_pairs is een [name, value] in de volgorde waarin een server ze zou sturen, en getheader vindt een naam in elke schrijfwijze, zoals de echte doet. fake_make_connection(response, calls) geeft een vervanger terug voor http.client.HTTPConnection. Geef hem mee als make_connection=, en elke stap die je code zet, komt op volgorde in calls terecht:
{"call": "connect", "host": "practice-api", "port": 8080, "timeout": 2.0}
{"call": "request", "method": "GET", "url": "/v1/items/1", "body": None, "headers": {"X-Practice-Name": "http-with-python"}}
{"call": "close"}
Met None als antwoord werpt getresponse() TimeoutError op, zoals een stille server de echte laat doen. Alles wat een test nodig heeft, is er: een gescripte status, headers in elke schrijfwijze, een body, en een verslag van of de verbinding werd gesloten.
Eén test, uitgewerkt
Hier is de vorm van een test voor een succes, met de eerste twee asserts uitgeschreven:
def test_get_json_decodes_a_success():
calls = []
response = scripted_response(200, "OK", [["Content-Type", "application/json"]], b'{"id": 1}')
record = wire.get_json("/v1/items/1", make_connection=fake_make_connection(response, calls))
assert record["class"] == "success"
assert record["data"] == {"id": 1}
Zet een antwoord en een lege lijst calls klaar, handel door wire.get_json aan te roepen, en controleer daarna met asserts het record en calls. Voeg fake_make_connection en scripted_response toe aan de regel from fakes import bovenaan tests/test_wire.py.
Voor een test die een test_a_close_inside_the_body_is_an_error roept de functie aan binnen try, keert terug vanuit de except-clausule voor de exception die het verwacht, en werpt na de try AssertionError op als de aanroep in plaats daarvan terugkeerde. calls[-1] is de laatst vastgelegde stap, en daar hoort een close te staan.
Mijlpalen
Een succestest, zoals die hierboven, die ook het item
connectincallscontroleert en dat het laatste item de close is.Eén test voor een 4xx en één voor een 5xx, elk met een JSON-foutbody, die de klasse en de gedecodeerde
"data"controleren.Een test met
fake_make_connection(None, calls)dieTimeoutErrorvanget_jsonverwacht en daarna controleert datcallseindigt met de close.Een test voor
report: een gescripte 504 geeft een regel die met504begint, en een stille server geeft een regel dietimed outzegt en geen504bevat.Alles wat verder het bewijzen waard is, zoals
Retry-Afterin een vreemde schrijfwijze, ofclassifyop een code die geen enkele lijst van jou noemt.
Schrijf elke test als een gewone functie def test_...(): zonder import wire, en roep binnen elke test wire.get_json(...), wire.report(...) en wire.classify(...) aan; voeg geen regel from wire import toe en sla die functies niet op onder namen bovenaan het bestand. Check my work zet via de from is geïmporteerd, zou het origineel vasthouden.
Voer het uit
Voer de tests uit vanuit de projectmap:
python -m pytest -q
Elke test zou moeten slagen, ook die uit hoofdstuk 1 en 2, en geen enkele heeft practice-api nodig. Als je wilt, voer report dan ook uit over de routes in README.md; deze uitvoering is voor jou en wordt nooit beoordeeld:
python -c "
import wire
for target in ['/v1/items?page=1&page_size=2', '/v1/scenarios/rate-limit?attempt=3', '/v1/items/99', '/v1/scenarios/server-error', '/v1/scenarios/timeout?delay_ms=750']:
print(target, wire.report(target, timeout=0.5))
"
De eerste vier regels noemen een status en zijn klasse: 200 success, daarna 429 client error, 404 client error en 500 server error. De laatste zegt dat je client een time-out kreeg, omdat een halve seconde korter is dan de 750 milliseconden van het scenario.
Druk daarna op Check my work. Je client leest nu elk antwoord dat practice-api kan sturen en zegt wat er gebeurde als er geen komt. In hoofdstuk 4 draait de verbinding om: je schrijft de server, en wire.py wordt het hulpmiddel dat je precies laat zien wat je server verstuurde.
Opdracht
Maak de client met de standaardbibliotheek af en bewijs hem met je eigen tests.
Zorg er in wire.py voor dat get_json het volledige record teruggeeft ("status", "reason", "headers", "content_type", "retry_after", "body", "class", "data") voor een antwoord van elke klasse, TimeoutError doorlaat met de verbinding gesloten; dat classify de klasse noemt van elke code van 100 tot en met 599; en dat report alleen een time-out omzet in een regel. Als les 1 tot en met 5 geslaagd zijn, klopt dit misschien al.
Schrijf in tests/test_wire.py minstens vijf tests die wire.get_json, wire.report of wire.classify aanroepen, met fakes.scripted_response en fakes.fake_make_connection. Dek een succes, een 4xx en een 5xx met JSON-foutbodies, een time-out (fake_make_connection(None, calls)) gevolgd door een controle dat de verbinding gesloten werd, en report op een 504 en op een time-out. Schrijf gewone def test_...(): zonder import wire en roep de functies daarlangs aan binnen elke test; voeg geen regel from wire import toe en sla ze niet op onder namen bovenaan het bestand. Houd de tests die al in het bestand staan.
Voer python -m pytest -q uit in de
Druk daarna op Check my work. Die roept get_json, classify en report aan met een vervangende verbinding en met statussen, headers en bodies die je niet hebt gezien. Daarna voert ze je tests uit, eerst tegen je eigen wire.py en daarna tegen vier kapotte clients: een die elke 4xx een succes noemt, een die de body van elke 4xx en 5xx weggooit, een die zijn eigen time-out meldt als 504, en een die de verbinding open laat als er geen antwoord aankomt. Je tests moeten allemaal slagen tegen de eerste, en minstens een moet mislukken tegen elk van de andere. Een test die naar het netwerk grijpt, mislukt in plaats van het te bereiken. Niets uit je terminal wordt beoordeeld.