doctest
— Testa interaktiva Python-exempel¶
Källkod: Lib/doctest.py
Modulen doctest
söker efter textstycken som ser ut som interaktiva Python-sessioner och kör sedan dessa sessioner för att verifiera att de fungerar exakt som de visas. Det finns flera vanliga sätt att använda doctest:
För att kontrollera att en moduls dokumentation är uppdaterad genom att verifiera att alla interaktiva exempel fortfarande fungerar enligt dokumentationen.
Att utföra regressionstest genom att verifiera att interaktiva exempel från en testfil eller ett testobjekt fungerar som förväntat.
Att skriva handledningsdokumentation för ett paket, rikligt illustrerad med exempel på inmatning och utmatning. Beroende på om exemplen eller den förklarande texten betonas, har detta en smak av ”litterat testande” eller ”körbar dokumentation”.
Här är en komplett men liten exempelmodul:
"""
This is the "example" module.
The example module supplies one function, factorial(). For example,
>>> factorial(5)
120
"""
def factorial(n):
"""Return the factorial of n, an exact integer >= 0.
>>> [factorial(n) for n in range(6)]
[1, 1, 2, 6, 24, 120]
>>> factorial(30)
265252859812191058636308480000000
>>> factorial(-1)
Traceback (most recent call last):
...
ValueError: n must be >= 0
Factorials of floats are OK, but the float must be an exact integer:
>>> factorial(30.1)
Traceback (most recent call last):
...
ValueError: n must be exact integer
>>> factorial(30.0)
265252859812191058636308480000000
It must also not be ridiculously large:
>>> factorial(1e100)
Traceback (most recent call last):
...
OverflowError: n too large
"""
import math
if not n >= 0:
raise ValueError("n must be >= 0")
if math.floor(n) != n:
raise ValueError("n must be exact integer")
if n+1 == n: # catch a value like 1e300
raise OverflowError("n too large")
result = 1
factor = 2
while factor <= n:
result *= factor
factor += 1
return result
if __name__ == "__main__":
import doctest
doctest.testmod()
Om du kör example.py
direkt från kommandoraden, kommer doctest
att utföra sin magi:
$ python example.py
$
Det finns ingen utdata! Det är normalt, och det betyder att alla exempel fungerade. Skicka -v
till skriptet, och doctest
skriver ut en detaljerad logg över vad det försöker göra, och skriver ut en sammanfattning i slutet:
$ python example.py -v
Trying:
factorial(5)
Expecting:
120
ok
Trying:
[factorial(n) for n in range(6)]
Expecting:
[1, 1, 2, 6, 24, 120]
ok
Och så vidare, för att slutligen sluta med:
Trying:
factorial(1e100)
Expecting:
Traceback (most recent call last):
...
OverflowError: n too large
ok
2 items passed all tests:
1 test in __main__
6 tests in __main__.factorial
7 tests in 2 items.
7 passed.
Test passed.
$
Det är allt du behöver veta för att börja använda doctest
på ett produktivt sätt! Hoppa in. Följande avsnitt ger fullständiga detaljer. Observera att det finns många exempel på doctests i Pythons standardtestsvit och bibliotek. Speciellt användbara exempel finns i standardtestfilen Lib/test/test_doctest/test_doctest.py
.
Tillagd i version 3.13: Utdata är färgade som standard och kan kontrolleras med hjälp av miljövariabler.
Enkel användning: Kontrollera exempel i dokumentsträngar¶
Det enklaste sättet att börja använda doctest (men inte nödvändigtvis det sätt som du kommer att fortsätta att göra det på) är att avsluta varje modul M
med:
if __name__ == "__main__":
import doctest
doctest.testmod()
doctest
undersöker sedan dokumentsträngar i modulen M
.
Om modulen körs som ett skript kommer exemplen i dokumentationen att köras och verifieras:
python M.py
Detta kommer inte att visa någonting om inte ett exempel misslyckas, i vilket fall de misslyckade exemplen och orsaken till misslyckandet skrivs ut till stdout, och den sista utdataraden är ***Test Failed*** N failures.
, där N är antalet exempel som misslyckades.
Kör det med -v
-omkopplaren istället:
python M.py -v
och en detaljerad rapport om alla exempel som provats skrivs ut till standardutmatningen, tillsammans med diverse sammanfattningar i slutet.
Du kan tvinga fram verbose-läge genom att skicka verbose=True
till testmod()
, eller förbjuda det genom att skicka verbose=False
. I något av dessa fall undersöks inte sys.argv
av testmod()
(så att skicka -v
eller inte har ingen effekt).
Det finns också en kommandoradsgenväg för att köra testmod()
, se avsnitt Användning på kommandoraden.
För mer information om testmod()
, se avsnitt Grundläggande API.
Enkel användning: Kontrollera exempel i en textfil¶
En annan enkel tillämpning av doctest är att testa interaktiva exempel i en textfil. Detta kan göras med funktionen testfile()
:
import doctest
doctest.testfile("exempel.txt")
Det korta skriptet exekverar och verifierar alla interaktiva Python-exempel som finns i filen example.txt
. Filens innehåll behandlas som om det vore en enda stor dokumentsträng; filen behöver inte innehålla ett Python-program! Till exempel kanske example.txt
innehåller detta:
The ``example`` module
======================
Using ``factorial``
-------------------
This is an example text file in reStructuredText format. First import
``factorial`` from the ``example`` module:
>>> from example import factorial
Now use it:
>>> factorial(6)
120
När man kör doctest.testfile("example.txt")
hittar man sedan felet i denna dokumentation:
File "./example.txt", line 14, in example.txt
Failed example:
factorial(6)
Expected:
120
Got:
720
Precis som med testmod()
kommer testfile()
inte att visa något om inte ett exempel misslyckas. Om ett exempel misslyckas, skrivs det eller de misslyckade exemplen och orsaken till misslyckandet ut till stdout, i samma format som testmod()
.
Som standard letar testfile()
efter filer i den anropande modulens katalog. Se avsnitt Grundläggande API för en beskrivning av de valfria argument som kan användas för att be den leta efter filer på andra platser.
I likhet med testmod()
kan testfile()
:s ordrikedom ställas in med kommandoradskommandot -v
eller med det valfria nyckelordsargumentet verbose.
Det finns också en kommandoradsgenväg för att köra testfile()
, se avsnitt Användning på kommandoraden.
För mer information om testfile()
, se avsnitt Grundläggande API.
Användning på kommandoraden¶
Modulen doctest
kan startas som ett skript från kommandoraden:
python -m doctest [-v] [-o OPTION] [-f] file [file ...]
- -v, --verbose¶
En detaljerad rapport över alla exempel som testats skrivs ut till standardutdata, tillsammans med diverse sammanfattningar i slutet:
python -m doctest -v example.py
Detta kommer att importera
example.py
som en fristående modul och köratestmod()
på den. Observera att det här kanske inte fungerar korrekt om filen är en del av ett paket och importerar andra undermoduler från det paketet.Om filnamnet inte slutar med
.py
, drardoctest
slutsatsen att den måste köras medtestfile()
istället:python -m doctest -v example.txt
- -o, --option <option>¶
Optionsflaggor styr olika aspekter av doctests beteende, se avsnitt Flaggor för alternativ.
Tillagd i version 3.4.
- -f, --fail-fast¶
Detta är en förkortning för
-o FAIL_FAST
.Tillagd i version 3.4.
Hur det fungerar¶
I det här avsnittet undersöks i detalj hur doctest fungerar: vilka dokumentsträngar det tittar på, hur det hittar interaktiva exempel, vilket exekveringskontext det använder, hur det hanterar undantag och hur alternativflaggor kan användas för att styra dess beteende. Detta är den information som du behöver för att skriva doctest-exempel; för information om hur du faktiskt kör doctest på dessa exempel, se följande avsnitt.
Vilka dokumentsträngar granskas?¶
Modulens dokumentsträng och alla funktions-, klass- och metoddokumentsträngar genomsöks. Objekt som importeras till modulen genomsöks inte.
Dessutom finns det fall där du vill att tester ska vara en del av en modul men inte en del av hjälptexten, vilket kräver att testerna inte ingår i dokumentsträngen. Doctest letar efter en variabel på modulnivå som heter __test__
och använder den för att hitta andra tester. Om M.__test__
finns måste den vara en dict, och varje post mappar ett (sträng)namn till ett funktionsobjekt, klassobjekt eller en sträng. Dokumentsträngar för funktions- och klassobjekt som hittas från M.__test__
söks igenom och strängar behandlas som om de vore dokumentsträngar. I utdata visas en nyckel K
i M.__test__
med namnet M.__test__.K
.
Placera till exempel det här kodblocket högst upp i example.py
:
__test__ = {
'numbers': """
>>> factorial(6)
720
>>> [factorial(n) for n in range(6)]
[1, 1, 2, 6, 24, 120]
"""
}
Värdet av example.__test__["numbers"]
kommer att behandlas som en docstring och alla tester i den kommer att köras. Det är viktigt att notera att värdet kan mappas till en funktion, ett klassobjekt eller en modul; om så är fallet söker doctest
igenom dem rekursivt efter docstrings, som sedan genomsöks efter tester.
Alla klasser som hittas genomsöks rekursivt på samma sätt för att testa dokumentsträngar i de metoder och nästlade klasser som ingår.
Anteckning
doctest
kan endast automatiskt upptäcka klasser och funktioner som är definierade på modulnivå eller inuti andra klasser.
Eftersom kapslade klasser och funktioner endast existerar när en yttre funktion anropas, kan de inte upptäckas. Definiera dem utanför för att göra dem synliga.
Hur känns Docstring-exempel igen?¶
I de flesta fall fungerar en kopia och klistra in av en interaktiv konsolsession bra, men doctest försöker inte göra en exakt emulering av något specifikt Python-skal.
>>> # comments are ignored
>>> x = 12
>>> x
12
>>> if x == 13:
... print("yes")
... else:
... print("no")
... print("NO")
... print("NO!!!")
...
no
NO
NO!!!
>>>
Any expected output must immediately follow the final '>>> '
or '... '
line containing the code, and the expected output (if any) extends to the next
'>>> '
or all-whitespace line.
Det finstilta:
Förväntad utdata kan inte innehålla en rad med enbart blanksteg, eftersom en sådan rad anses signalera slutet på förväntad utdata. Om förväntad utdata innehåller en blankrad, lägg till
<BLANKLINE>
i ditt doctest-exempel varje gång en blankrad förväntas.Alla hårda tabbtecken expanderas till mellanslag med tabbstopp i 8 kolumner. Tabbar i utdata som genereras av den testade koden ändras inte. Eftersom alla hårda tabbar i exempelutmatningen expanderas innebär detta att om kodutmatningen innehåller hårda tabbar är det enda sättet för doctestet att bli godkänt om alternativet
NORMALIZE_WHITESPACE
eller directive är i kraft. Alternativt kan testet skrivas om för att fånga utdata och jämföra det med ett förväntat värde som en del av testet. Den här hanteringen av tabbar i källan har kommit till genom försök och misstag och har visat sig vara det minst felbenägna sättet att hantera dem. Det är möjligt att använda en annan algoritm för att hantera tabbar genom att skriva en egenDocTestParser
-klass.Utdata till stdout fångas upp, men inte utdata till stderr (spårningar av undantag fångas upp på ett annat sätt).
Om du fortsätter en rad med hjälp av backslash i en interaktiv session, eller av någon annan anledning använder backslash, bör du använda en rå docstring, som bevarar dina backslash exakt som du skriver dem:
>>> def f(x): ... r'''Backslashes in a raw docstring: m\n''' ... >>> print(f.__doc__) Backslashes in a raw docstring: m\n
I annat fall tolkas backslash som en del av strängen. Till exempel skulle
n
ovan tolkas som ett tecken för ny rad. Alternativt kan du fördubbla varje backslash i doctest-versionen (och inte använda en rå sträng):>>> def f(x): ... '''Backslashes in a raw docstring: m\\n''' ... >>> print(f.__doc__) Backslashes in a raw docstring: m\n
Startkolumnen spelar ingen roll:
>>> assert "Easy!" >>> import math >>> math.floor(1.9) 1
and as many leading whitespace characters are stripped from the expected output as appeared in the initial
'>>> '
line that started the example.
Vad är exekveringskontexten?¶
Som standard, varje gång doctest
hittar en dokumentsträng att testa, använder den en grunt kopia av M
:s globaler, så att körning av tester inte ändrar modulens verkliga globaler, och så att ett test i M
inte kan lämna efter sig smulor som av misstag tillåter ett annat test att fungera. Detta innebär att exempel fritt kan använda alla namn som definieras på toppnivå i M
, och namn som definieras tidigare i den dokumentsträng som körs. Exempel kan inte se namn som definierats i andra dokumentsträngar.
Du kan tvinga fram användning av din egen dict som exekveringskontext genom att skicka globs=your_dict
till testmod()
eller testfile()
istället.
Hur är det med undantag?¶
Inga problem, förutsatt att spårningen är den enda utdata som exemplet ger: klistra bara in spårningen. [1] Eftersom spårningar innehåller detaljer som sannolikt kommer att ändras snabbt (till exempel exakta filsökvägar och radnummer) är detta ett fall där doctest arbetar hårt för att vara flexibel i vad den accepterar.
Ett enkelt exempel:
>>> [1, 2, 3].remove(42)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: list.remove(x): x not in list
Detta doctest lyckas om ValueError
tas upp, med list.remove(x): x not in list
detalj som visas.
Den förväntade utdata för ett undantag måste börja med en spårningsrubrik, som kan vara någon av följande två rader, indragna på samma sätt som den första raden i exemplet:
Traceback (most recent call last):
Traceback (innermost last):
Traceback-huvudet följs av en valfri traceback-stack, vars innehåll ignoreras av doctest. Traceback-stacken utelämnas vanligtvis eller kopieras ordagrant från en interaktiv session.
Efter spårningsstacken följer den mest intressanta delen: raden/raderna som innehåller undantagstypen och detaljerna. Detta är vanligtvis den sista raden i en spårning, men kan sträcka sig över flera rader om undantaget har en detalj med flera rader:
>>> raise ValueError('multi\n line\ndetail')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: multi
line
detail
De tre sista raderna (som börjar med ValueError
) jämförs med undantagets typ och detalj, och resten ignoreras.
Bästa praxis är att utelämna traceback-stacken, såvida den inte tillför ett betydande dokumentationsvärde till exemplet. Så det sista exemplet är förmodligen bättre som:
>>> raise ValueError('multi\n line\ndetail')
Traceback (most recent call last):
...
ValueError: multi
line
detail
Observera att spårningar behandlas mycket speciellt. I synnerhet i det omskrivna exemplet är användningen av ...
oberoende av doctests ELLIPSIS
-alternativ. Ellipsen i det exemplet kan utelämnas, eller lika gärna vara tre (eller trehundra) kommatecken eller siffror, eller en indragen utskrift av en Monty Python-sketch.
Vissa detaljer bör du läsa en gång, men behöver inte komma ihåg:
Doctest kan inte gissa om den förväntade utmatningen kommer från en exception traceback eller från vanlig utskrift. Så, t.ex., ett exempel som förväntar sig
ValueError: 42 is prime
kommer att godkännas oavsett omValueError
faktiskt uppstår eller om exemplet bara skriver ut den spårningstexten. I praktiken börjar vanliga utdata sällan med en spårningshuvudrad, så det här skapar inga verkliga problem.Varje rad i spårningsstacken (om sådan finns) måste vara indragen längre än den första raden i exemplet, eller börja med ett icke-alfanumeriskt tecken. Den första raden efter spårningshuvudet som är indragen på samma sätt och som börjar med ett alfanumeriskt tecken anses vara början på undantagsdetaljen. Naturligtvis gör detta det rätta för äkta spårningar.
När doctest-alternativet
IGNORE_EXCEPTION_DETAIL
anges ignoreras allt som följer efter kolon längst till vänster och all modulinformation i undantagsnamnet.Det interaktiva skalet utelämnar spårningshuvudraden för vissa
SyntaxError
. Men doctest använder spårningshuvudraden för att skilja undantag från icke-undantag. Så i det sällsynta fall då du behöver testa ettSyntaxError
som utelämnar traceback-rubriken, måste du manuellt lägga till traceback-rubriken i ditt testexempel.
För vissa undantag visar Python felets position med hjälp av
^
-markörer och tildes:>>> 1 + None File "<stdin>", line 1 1 + None ~~^~~~~~ TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'
Eftersom raderna som visar felets position kommer före undantagstypen och detaljerna, kontrolleras de inte av doctest. Till exempel skulle följande test godkännas, även om det placerar
^
-markören på fel plats:>>> 1 + None File "<stdin>", line 1 1 + None ^~~~~~~~ TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'
Flaggor för alternativ¶
Ett antal optionsflaggor styr olika aspekter av doctests beteende. Symboliska namn för flaggorna anges som modulkonstanter, som kan bitwise ORed ihop och skickas till olika funktioner. Namnen kan också användas i doctest-direktiv, och kan skickas till doctests kommandoradsgränssnitt via alternativet -o
.
Den första gruppen av alternativ definierar testets semantik och styr aspekter av hur doctest avgör om den faktiska utdata stämmer överens med ett exempels förväntade utdata:
- doctest.DONT_ACCEPT_TRUE_FOR_1¶
Som standard, om ett förväntat utdatablock innehåller bara
1
, anses ett faktiskt utdatablock som innehåller bara1
eller baraTrue
vara en matchning, och på samma sätt för0
kontraFalse
. NärDONT_ACCEPT_TRUE_FOR_1
anges tillåts ingen av dessa substitutioner. Standardbeteendet tar hänsyn till att Python ändrade returtypen för många funktioner från heltal till boolean; doctests som förväntar sig ”little integer”-utdata fungerar fortfarande i dessa fall. Detta alternativ kommer förmodligen att försvinna, men inte på flera år.
- doctest.DONT_ACCEPT_BLANKLINE¶
Om ett förväntat utdatablock innehåller en rad som bara innehåller strängen
<BLANKLINE>
, kommer den raden som standard att matcha en tom rad i den faktiska utdatan. Eftersom en blank rad verkligen avgränsar den förväntade utdata, är detta det enda sättet att kommunicera att en blank rad förväntas. NärDONT_ACCEPT_BLANKLINE
anges är denna substitution inte tillåten.
- doctest.NORMALIZE_WHITESPACE¶
När detta anges behandlas alla sekvenser av blanktecken (blanksteg och nya linjer) som lika. Alla sekvenser av blanksteg i den förväntade utskriften kommer att matcha alla sekvenser av blanksteg i den faktiska utskriften. Som standard måste blanksteg matcha exakt.
NORMALIZE_WHITESPACE
är särskilt användbart när en rad med förväntad utdata är mycket lång och du vill lägga den över flera rader i källan.
- doctest.ELLIPSIS¶
När detta anges kan en ellipsmarkör (
...
) i den förväntade utdata matcha vilken delsträng som helst i den faktiska utdata. Detta inkluderar substrängar som sträcker sig över radgränser och tomma substrängar, så det är bäst att hålla användningen av detta enkel. Komplicerade användningar kan leda till samma typ av ”oops, det matchade för mycket!” överraskningar som.*
är benägen att i reguljära uttryck.
- doctest.IGNORE_EXCEPTION_DETAIL¶
När detta anges godkänns doctests som väntar på undantag så länge ett undantag av den förväntade typen uppstår, även om detaljerna (meddelande och fullständigt kvalificerat undantagsnamn) inte stämmer överens.
Till exempel kommer ett exempel som förväntar sig
ValueError: 42
kommer att godkännas om det faktiska undantaget ärValueError: 3*14
, men kommer att misslyckas om, säg, ettTypeError
tas upp istället. Den kommer också att ignorera alla fullständigt kvalificerade namn som ingår före undantagsklassen, vilket kan variera mellan implementationer och versioner av Python och den kod / bibliotek som används. Därför kommer alla dessa tre variationer att fungera med den angivna flaggan:>>> raise Exception('message') Traceback (most recent call last): Exception: message >>> raise Exception('message') Traceback (most recent call last): builtins.Exception: message >>> raise Exception('message') Traceback (most recent call last): __main__.Exception: message
Observera att
ELLIPSIS
också kan användas för att ignorera detaljerna i undantagsmeddelandet, men ett sådant test kan fortfarande misslyckas beroende på om modulnamnet finns eller matchar exakt.Ändrad i version 3.2:
IGNORE_EXCEPTION_DETAIL
ignorerar nu även all information som rör den modul som innehåller det undantag som testas.
- doctest.SKIP¶
Om detta anges ska exemplet inte köras alls. Detta kan vara användbart i sammanhang där doctest-exempel fungerar som både dokumentation och testfall, och ett exempel bör inkluderas för dokumentationsändamål, men inte bör kontrolleras. Exemplets utdata kan t.ex. vara slumpmässig, eller så kan exemplet vara beroende av resurser som inte är tillgängliga för testföraren.
SKIP-flaggan kan också användas för att tillfälligt ”kommentera bort” exempel.
- doctest.COMPARISON_FLAGS¶
En bitmask som kombinerar alla jämförelseflaggorna ovan.
Den andra gruppen av alternativ styr hur testfel rapporteras:
- doctest.REPORT_UDIFF¶
När så anges visas fel som omfattar förväntade och faktiska utdata på flera rader med en enhetlig diff.
- doctest.REPORT_CDIFF¶
Om detta anges kommer fel som innehåller flera rader med förväntade och faktiska utdata att visas med hjälp av en kontextdiff.
- doctest.REPORT_NDIFF¶
När detta anges beräknas skillnaderna av
difflib.Differ
, som använder samma algoritm som det populära verktygetndiff.py
. Detta är den enda metod som markerar skillnader inom rader såväl som mellan rader. Om t.ex. en rad med förväntad utmatning innehåller siffran1
medan den faktiska utmatningen innehåller bokstavenl
, infogas en rad med en caret som markerar de felaktiga kolumnpositionerna.
- doctest.REPORT_ONLY_FIRST_FAILURE¶
När detta anges visas det första misslyckade exemplet i varje doctest, men utdata för alla återstående exempel undertrycks. Detta kommer att förhindra doctest från att rapportera korrekta exempel som misslyckas på grund av tidigare misslyckanden; men det kan också dölja felaktiga exempel som misslyckas oberoende av det första misslyckandet. När
REPORT_ONLY_FIRST_FAILURE
anges, körs de återstående exemplen fortfarande och räknas fortfarande in i det totala antalet fel som rapporteras; endast utdata undertrycks.
- doctest.FAIL_FAST¶
När den anges avslutas programmet efter det första misslyckade exemplet och försöker inte köra de återstående exemplen. Antalet misslyckanden som rapporteras blir således högst 1. Denna flagga kan vara användbar under felsökning, eftersom exempel efter det första misslyckandet inte ens kommer att producera felsökningsutdata.
- doctest.REPORTING_FLAGS¶
En bitmask som kombinerar alla rapporteringsflaggor ovan.
Det finns också ett sätt att registrera nya alternativflaggnamn, men detta är inte användbart om du inte tänker utöka doctest
internals via underklassning:
- doctest.register_optionflag(name)¶
Skapa en ny alternativflagga med ett givet namn och returnera den nya flaggans heltalsvärde.
register_optionflag()
kan användas när du underklassarOutputChecker
ellerDocTestRunner
för att skapa nya alternativ som stöds av dina underklasser.register_optionflag()
bör alltid anropas med följande idiom:MY_FLAG = register_optionflag('MY_FLAG')
Direktiv¶
Doctest-direktiv kan användas för att ändra alternativflaggor för ett enskilt exempel. Doctest-direktiv är speciella Python-kommentarer som följer efter ett exempels källkod:
directive: "#" "doctest:"directive_options
directive_options:directive_option
(","directive_option
)* directive_option:on_or_off
directive_option_name
on_or_off: "+" | "-" directive_option_name: "DONT_ACCEPT_BLANKLINE" | "NORMALIZE_WHITESPACE" | ...
Whitespace är inte tillåtet mellan +
eller -
och namnet på direktivalternativet. Namnet på direktivalternativet kan vara vilket som helst av de flaggnamn för alternativ som förklaras ovan.
Ett exempels doctest-direktiv ändrar doctests beteende för det enskilda exemplet. Använd +
för att aktivera det angivna beteendet, eller -
för att inaktivera det.
Det här testet är till exempel godkänt:
>>> print(list(range(20))) # doctest: +NORMALIZE_WHITESPACE
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
Utan direktivet skulle det misslyckas, både för att den faktiska utmatningen inte har två blanksteg före de ensiffriga listelementen och för att den faktiska utmatningen är på en enda rad. Det här testet är också godkänt och kräver också ett direktiv för att bli det:
>>> print(list(range(20))) # doctest: +ELLIPSIS
[0, 1, ..., 18, 19]
Flera direktiv kan användas på en och samma fysiska rad, åtskilda med kommatecken:
>>> print(list(range(20))) # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
[0, 1, ..., 18, 19]
Om flera direktivkommentarer används för ett och samma exempel, kombineras de:
>>> print(list(range(20))) # doctest: +ELLIPSIS
... # doctest: +NORMALIZE_WHITESPACE
[0, 1, ..., 18, 19]
Som det föregående exemplet visar kan du lägga till ...
rader till ditt exempel som bara innehåller direktiv. Detta kan vara användbart när ett exempel är för långt för att ett direktiv ska rymmas på samma rad:
>>> print(list(range(5)) + list(range(10, 20)) + list(range(30, 40)))
... # doctest: +ELLIPSIS
[0, ..., 4, 10, ..., 19, 30, ..., 39]
Observera att eftersom alla alternativ är inaktiverade som standard och direktiv endast gäller för det exempel de förekommer i, är aktivering av alternativ (via +
i ett direktiv) vanligtvis det enda meningsfulla valet. Alternativflaggor kan emellertid också skickas till funktioner som kör doctests och fastställa olika standardvärden. I sådana fall kan det vara användbart att inaktivera ett alternativ via -
i ett direktiv.
Varningar¶
doctest
är seriös när det gäller att kräva exakta matchningar i förväntad utdata. Om inte ens ett enda tecken matchar, misslyckas testet. Detta kommer förmodligen att överraska dig några gånger, eftersom du lär dig exakt vad Python gör och inte garanterar om utdata. Till exempel, när du skriver ut en uppsättning garanterar Python inte att elementen skrivs ut i någon särskild ordning, så ett test som
>>> foo()
{"spam", "eggs"}
är sårbar! En lösning är att göra
>>> foo() == {"spam", "eggs"}
True
istället. Ett annat är att göra
>>> d = sorted(foo())
>>> d
['eggs', 'spam']
Det finns fler, men du förstår säkert.
En annan dålig idé är att skriva ut saker som innehåller en objektadress, t.ex
>>> id(1.0) # certain to fail some of the time
7948648
>>> class C: pass
>>> C() # the default repr() for instances embeds an address
<C object at 0x00AC18F0>
Direktivet ELLIPSIS
ger en bra metod för det sista exemplet:
>>> C() # doctest: +ELLIPSIS
<C object at 0x...>
Flyttal är också föremål för små variationer i utdata mellan plattformar, eftersom Python använder plattformens C-bibliotek för vissa beräkningar med flyttal, och C-biblioteken varierar mycket i kvalitet här:
>>> 1000**0.1 # risky
1.9952623149688797
>>> round(1000**0.1, 9) # safer
1.995262315
>>> print(f'{1000**0.1:.4f}') # much safer
1.9953
Tal av formen I/2.**J
är säkra på alla plattformar, och jag hittar ofta på doctest-exempel för att producera tal av den formen:
>>> 3./4 # utterly safe
0.75
Enkla bråk är också lättare för människor att förstå, och det ger bättre dokumentation.
Grundläggande API¶
Funktionerna testmod()
och testfile()
ger ett enkelt gränssnitt till doctest som bör vara tillräckligt för de flesta grundläggande användningsområden. För en mindre formell introduktion till dessa två funktioner, se avsnitten Enkel användning: Kontrollera exempel i dokumentsträngar och Enkel användning: Kontrollera exempel i en textfil.
- doctest.testfile(filename, module_relative=True, name=None, package=None, globs=None, verbose=None, report=True, optionflags=0, extraglobs=None, raise_on_error=False, parser=DocTestParser(), encoding=None)¶
Alla argument utom filnamn är valfria och bör anges i nyckelordsform.
Testa exempel i filen med namnet filnamn. Returnerar
(misslyckande_antal, test_antal)
.Det valfria argumentet module_relative anger hur filnamnet ska tolkas:
Om module_relative är
True
(standard), anger filename en OS-oberoende modulrelativ sökväg. Som standard är denna sökväg relativ till den anropande modulens katalog, men om argumentet package anges är den relativ till det paketet. För att säkerställa operativsystemsoberoende bör filename använda tecknet/
för att separera sökvägssegment och får inte vara en absolut sökväg (dvs. den får inte börja med/
).Om module_relative är
False
, anger filnamn en OS-specifik sökväg. Sökvägen kan vara absolut eller relativ; relativa sökvägar löses med avseende på den aktuella arbetskatalogen.
Det valfria argumentet name anger namnet på testet; som standard, eller om
None
, användsos.path.basename(filnamn)
.Valfritt argument package är ett Python-paket eller namnet på ett Python-paket vars katalog ska användas som baskatalog för ett modulrelativt filnamn. Om inget paket anges används den anropande modulens katalog som baskatalog för modulrelativa filnamn. Det är ett fel att ange package om module_relative är
False
.Det valfria argumentet globs ger en dict som ska användas som globaler när exempel körs. En ny ytlig kopia av denna dict skapas för doctestet, så att dess exempel börjar med ett rent blad. Som standard, eller om
None
, används en ny tom dict.Det valfria argumentet extraglobs ger en dict som sammanfogats till de globaler som används för att exekvera exempel. Detta fungerar som
dict.update()
: om globs och extraglobs har en gemensam nyckel, visas det associerade värdet i extraglobs i den kombinerade dict. Som standard, eller omNone
, används inga extra globaler. Detta är en avancerad funktion som gör det möjligt att parametrisera doctests. Till exempel kan ett doctest skrivas för en basklass, med ett generiskt namn för klassen, och sedan återanvändas för att testa valfritt antal underklasser genom att skicka en extraglobs-dict som mappar det generiska namnet till den underklass som ska testas.Det valfria argumentet verbose skriver ut en massa saker om det är sant, och skriver bara ut fel om det är falskt; som standard, eller om
None
, är det sant om och endast om'-v'
finns isys.argv
.Det valfria argumentet report skriver ut en sammanfattning i slutet när det är sant, annars skrivs ingenting ut i slutet. I verbose-läge är sammanfattningen detaljerad, annars är sammanfattningen mycket kort (i själva verket tom om alla tester är godkända).
Det valfria argumentet optionflags (standardvärde
0
) tar bitwise OR av optionsflaggor. Se avsnitt Flaggor för alternativ.Det valfria argumentet raise_on_error är som standard false. Om det är sant utlöses ett undantag vid det första felet eller oväntade undantaget i ett exempel. Detta gör att misslyckanden kan felsökas efteråt. Standardbeteendet är att fortsätta köra exempel.
Det valfria argumentet parser anger en
DocTestParser
(eller underklass) som ska användas för att extrahera tester från filerna. Standardvärdet är en normal parser (dvs.DocTestParser()
).Det valfria argumentet encoding anger en kodning som ska användas för att konvertera filen till unicode.
- doctest.testmod(m=None, name=None, globs=None, verbose=None, report=True, optionflags=0, extraglobs=None, raise_on_error=False, exclude_empty=False)¶
Alla argument är valfria och alla utom m ska anges i nyckelordsform.
Testexempel i dokumentationssträngar i funktioner och klasser som kan nås från modul m (eller modul
__main__
om m inte anges eller ärNone
), med början im.__doc__
.Testa även exempel som kan nås från dict
m.__test__
, om den finns.m.__test__
mappar namn (strängar) till funktioner, klasser och strängar; funktions- och klassdokstrings söks efter exempel; strängar söks direkt, som om de vore dokstrings.Endast dokumentsträngar som är kopplade till objekt som tillhör modul m söks.
Return
(failure_count, test_count)
.Det valfria argumentet name anger namnet på modulen; som standard, eller om
None
, användsm.__name__
.Det valfria argumentet exclude_empty är som standard false. Om det är sant utesluts objekt för vilka inga doctests hittas från att beaktas. Standardvärdet är ett hack för bakåtkompatibilitet, så att kod som fortfarande använder
doctest.master.summarize
i kombination medtestmod()
fortsätter att få utdata för objekt utan tester. Argumentet exclude_empty till den nyareDocTestFinder
-konstruktorn är som standard true.De valfria argumenten extraglobs, verbose, report, optionflags, raise_on_error och globs är desamma som för funktionen
testfile()
ovan, förutom att globs som standard ärm.__dict__
.
- doctest.run_docstring_examples(f, globs, verbose=False, name='NoName', compileflags=None, optionflags=0)¶
Testexempel som är associerade med objektet f; f kan t.ex. vara en sträng, en modul, en funktion eller ett klassobjekt.
En ytlig kopia av ordboksargumentet globs används för exekveringskontexten.
Det valfria argumentet name används i felmeddelanden och är som standard
"NoName"
.Om det valfria argumentet verbose är true, genereras utdata även om det inte finns några fel. Som standard genereras utdata endast i händelse av ett exempel på fel.
Det valfria argumentet compileflags anger den uppsättning flaggor som ska användas av Python-kompilatorn när exemplen körs. Som standard, eller om
None
, härleds flaggor som motsvarar den uppsättning framtida funktioner som finns i globs.Det valfria argumentet optionflags fungerar som för funktionen
testfile()
ovan.
Unittest API¶
När din samling av doctest’ed-moduler växer, kommer du att vilja ha ett sätt att köra alla deras doctests systematiskt. doctest
tillhandahåller två funktioner som kan användas för att skapa unittest
testsviter från moduler och textfiler som innehåller doctests. För att integrera med unittest
testupptäckt, inkludera en load_tests funktion i din testmodul:
import unittest
import doctest
import my_module_with_doctests
def load_tests(loader, tests, ignore):
tests.addTests(doctest.DocTestSuite(my_module_with_doctests))
return tests
Det finns två huvudfunktioner för att skapa unittest.TestSuite
-instanser från textfiler och moduler med doctests:
- doctest.DocFileSuite(*paths, module_relative=True, package=None, setUp=None, tearDown=None, globs=None, optionflags=0, parser=DocTestParser(), encoding=None)¶
Konvertera doctest-tester från en eller flera textfiler till en
unittest.TestSuite
.Den returnerade
unittest.TestSuite
ska köras av unittest-ramverket och kör de interaktiva exemplen i varje fil. Om ett exempel i någon fil misslyckas, misslyckas det syntetiserade enhetstestet och ettfailureException
-undantag skapas som visar namnet på filen som innehåller testet och ett (ibland ungefärligt) radnummer. Om alla exempel i en fil hoppas över markeras även det syntetiserade enhetstestet som överhoppat.Skicka en eller flera sökvägar (som strängar) till textfiler som ska undersökas.
Alternativ kan anges som nyckelordsargument:
Det valfria argumentet module_relative anger hur filnamnen i paths ska tolkas:
Om module_relative är
True
(standard), anger varje filnamn i paths en OS-oberoende modulrelativ sökväg. Som standard är denna sökväg relativ till den anropande modulens katalog, men om argumentet package anges är den relativ till det paketet. För att säkerställa operativsystemsoberoende bör varje filnamn använda tecknet/
för att separera sökvägssegment och får inte vara en absolut sökväg (dvs. den får inte börja med/
).Om module_relative är
False
, anger varje filnamn i paths en OS-specifik sökväg. Sökvägen kan vara absolut eller relativ; relativa sökvägar löses med avseende på den aktuella arbetskatalogen.
Det valfria argumentet package är ett Python-paket eller namnet på ett Python-paket vars katalog ska användas som baskatalog för modulrelativa filnamn i paths. Om inget paket anges används den anropande modulens katalog som baskatalog för modulrelativa filnamn. Det är ett fel att ange package om module_relative är
False
.Det valfria argumentet setUp anger en konfigurationsfunktion för testsviten. Denna anropas innan testerna i varje fil körs. Funktionen setUp får ett objekt av
DocTest
. Funktionen setUp kan komma åt testglobalerna som attributetglobs
för det test som skickas.Det valfria argumentet tearDown anger en nedmonteringsfunktion för testsviten. Denna anropas efter att testerna i varje fil har körts. Funktionen tearDown kommer att få ett objekt av
DocTest
. Funktionen tearDown kan komma åt testglobalerna som attributetglobs
i det test som skickas.Det valfria argumentet globs är en ordbok som innehåller de första globala variablerna för testerna. En ny kopia av denna ordbok skapas för varje test. Som standard är globs en ny tom ordbok.
Det valfria argumentet optionflags anger standardalternativen för doctest för testerna, som skapas genom att kombinera enskilda alternativflaggor. Se avsnitt Flaggor för alternativ. Se funktionen
set_unittest_reportflags()
nedan för ett bättre sätt att ställa in rapporteringsalternativ.Det valfria argumentet parser anger en
DocTestParser
(eller underklass) som ska användas för att extrahera tester från filerna. Standardvärdet är en normal parser (dvs.DocTestParser()
).Det valfria argumentet encoding anger en kodning som ska användas för att konvertera filen till unicode.
Den globala
__file__
läggs till i de globaler som tillhandahålls för doctests som laddas från en textfil medDocFileSuite()
.
- doctest.DocTestSuite(module=None, globs=None, extraglobs=None, test_finder=None, setUp=None, tearDown=None, optionflags=0, checker=None)¶
Konvertera doctest-tester för en modul till en
unittest.TestSuite
.Den returnerade
unittest.TestSuite
ska köras av unittest-ramverket och kör varje doctest i modulen. Varje dokumentsträng körs som ett separat enhetstest. Om något av doctesterna misslyckas, misslyckas det syntetiserade enhetstestet och ettunittest.TestCase.failureException
-undantag skapas som visar namnet på filen som innehåller testet och ett (ibland ungefärligt) radnummer. Om alla exempel i en dokumentsträng hoppas över, kommerDet valfria argumentet module anger vilken modul som ska testas. Det kan vara ett modulobjekt eller ett (eventuellt prickat) modulnamn. Om det inte anges används den modul som anropar denna funktion.
Det valfria argumentet globs är en ordbok som innehåller de första globala variablerna för testerna. En ny kopia av denna dictionary skapas för varje test. Som standard är globs modulens
__dict__
.Det valfria argumentet extraglobs anger en extra uppsättning globala variabler som slås samman med globs. Som standard används inga extra globala variabler.
Valfritt argument test_finder är
DocTestFinder
-objektet (eller en direkt ersättare) som används för att extrahera doctests från modulen.De valfria argumenten setUp, tearDown och optionflags är desamma som för funktionen
DocFileSuite()
ovan, men de anropas för varje dokumentsträng.Denna funktion använder samma sökteknik som
testmod()
.Ändrad i version 3.5:
DocTestSuite()
returnerar en tomunittest.TestSuite
om modul inte innehåller några docstrings istället för att geValueError
.
Under täckmanteln skapar DocTestSuite()
en unittest.TestSuite
av doctest.DocTestCase
-instanser, och DocTestCase
är en underklass till unittest.TestCase
. DocTestCase
dokumenteras inte här (det är en intern detalj), men att studera dess kod kan svara på frågor om de exakta detaljerna i unittest
-integrationen.
På samma sätt skapar DocFileSuite()
en unittest.TestSuite
av doctest.DocFileCase
-instanser, och DocFileCase
är en subklass av DocTestCase
.
Så båda sätten att skapa en unittest.TestSuite
kör instanser av DocTestCase
. Detta är viktigt av en subtil anledning: när du kör doctest
-funktioner själv, kan du styra doctest
-alternativen som används direkt, genom att skicka alternativflaggor till doctest
-funktioner. Men om du skriver ett unittest
-ramverk, kontrollerar unittest
i slutändan när och hur tester körs. Ramverkets författare vill vanligtvis kontrollera doctest
rapporteringsalternativ (kanske, t.ex., specificerade av kommandoradsalternativ), men det finns inget sätt att skicka alternativ genom unittest
till doctest
testlöpare.
Av denna anledning stödjer doctest
också ett begrepp som doctest
som rapporterar flaggor som är specifika för unittest
-stöd, via denna funktion:
- doctest.set_unittest_reportflags(flags)¶
Ange vilka
doctest
-rapporteringsflaggor som ska användas.Argument flags tar bitvis ELLER av alternativflaggor. Se avsnitt Flaggor för alternativ. Endast ”rapporteringsflaggor” kan användas.
Detta är en modul-global inställning, och påverkar alla framtida doctest som körs av modulen
unittest
:runTest()
-metoden iDocTestCase
tittar på de alternativflaggor som specificerades för testfallet närDocTestCase
-instansen konstruerades. Om inga rapporteringsflaggor specificerades (vilket är det typiska och förväntade fallet),doctest
unittest
rapporteringsflaggor är bitwise ORed i alternativflaggorna, och alternativflaggorna så förstärkta skickas tillDocTestRunner
instansen skapad för att köra doctestet. Om några rapporteringsflaggor specificerades närDocTestCase
-instansen konstruerades, ignorerasdoctest
:sunittest
rapporteringsflaggor.Funktionen returnerar värdet på
unittest
-rapporteringsflaggorna som gällde innan funktionen anropades.
Avancerat API¶
Det grundläggande API:et är en enkel wrapper som är avsedd att göra doctest lätt att använda. Det är ganska flexibelt och bör uppfylla de flesta användares behov; men om du behöver mer finkornig kontroll över testningen eller vill utöka doctests funktioner bör du använda det avancerade API:et.
Det avancerade API:et kretsar kring två containerklasser som används för att lagra de interaktiva exempel som hämtas från doctest-fall:
Exempel
: En enda Python statement, parat med dess förväntade resultat.DocTest
: En samling avExample
, vanligtvis extraherade från en enda dokumentsträng eller textfil.
Ytterligare bearbetningsklasser definieras för att hitta, analysera och köra samt kontrollera doctest-exempel:
DocTestFinder
: Hittar alla dokumentsträngar i en given modul och använder enDocTestParser
för att skapa enDocTest
från varje dokumentsträng som innehåller interaktiva exempel.DocTestParser
: Skapar ettDocTest
-objekt från en sträng (t.ex. ett objekts docstring).DocTestRunner
: Exekverar exemplen i enDocTest
och använder enOutputChecker
för att verifiera utdata.OutputChecker
: Jämför den faktiska utdata från ett doctest-exempel med den förväntade utdata och avgör om de stämmer överens.
Relationerna mellan dessa bearbetningsklasser sammanfattas i följande diagram:
list of:
+------+ +---------+
|module| --DocTestFinder-> | DocTest | --DocTestRunner-> results
+------+ | ^ +---------+ | ^ (printed)
| | | Example | | |
v | | ... | v |
DocTestParser | Example | OutputChecker
+---------+
DocTest-objekt¶
- class doctest.DocTest(examples, globs, name, filename, lineno, docstring)¶
En samling doctest-exempel som bör köras i ett enda namnrymd. Argumenten i konstruktorn används för att initiera attributen med samma namn.
DocTest
definierar följande attribut. De initialiseras av konstruktören och bör inte modifieras direkt.- examples¶
En lista med
Example
-objekt som kodar för de enskilda interaktiva Python-exempel som ska köras av detta test.
- globs¶
Namnrymden (även kallad globals) som exemplen ska köras i. Detta är en ordbok som mappar namn till värden. Alla ändringar i namnrymden som görs av exemplen (t.ex. bindning av nya variabler) kommer att återspeglas i
globs
efter att testet har körts.
- name¶
Ett strängnamn som identifierar
DocTest
. Vanligtvis är detta namnet på det objekt eller den fil som testet extraherades från.
- filename¶
Namnet på filen som detta
DocTest
extraherades från; ellerNone
om filnamnet är okänt, eller omDocTest
inte extraherades från en fil.
- lineno¶
Radnumret i
filename
där dennaDocTest
börjar, ellerNone
om radnumret inte är tillgängligt. Radnumret är nollbaserat i förhållande till början av filen.
- docstring¶
Den sträng som testet extraherades från, eller
None
om strängen inte är tillgänglig, eller om testet inte extraherades från en sträng.
Exempel på objekt¶
- class doctest.Example(source, want, exc_msg=None, lineno=0, indent=0, options=None)¶
Ett enda interaktivt exempel som består av en Python-sats och dess förväntade utdata. Argumenten i konstruktorn används för att initiera attributen med samma namn.
Example
definierar följande attribut. De initialiseras av konstruktören och bör inte modifieras direkt.- source¶
En sträng som innehåller exemplets källkod. Källkoden består av en enda Python-sats och avslutas alltid med en ny rad; konstruktören lägger till en ny rad när det behövs.
- want¶
Den förväntade utdata från körning av exemplets källkod (antingen från stdout eller en spårning vid undantag).
want
slutar med en ny rad om ingen utdata förväntas, i vilket fall det är en tom sträng. Konstruktören lägger till en ny rad när det behövs.
- exc_msg¶
Det undantagsmeddelande som genereras av exemplet, om exemplet förväntas generera ett undantag; eller
None
om det inte förväntas generera ett undantag. Detta undantagsmeddelande jämförs med returvärdet förtraceback.format_exception_only()
.exc_msg
slutar med en ny rad om det inte ärNone
. Konstruktören lägger till en ny rad om det behövs.
- lineno¶
Radnumret i den sträng som innehåller detta exempel där exemplet börjar. Radnumret är nollbaserat i förhållande till början av den sträng som innehåller exemplet.
- indent¶
Exemplets indrag i den innehållande strängen, dvs. antalet mellanslagstecken som föregår exemplets första prompt.
- options¶
En ordbok som mappar från alternativflaggor till
True
ellerFalse
, som används för att åsidosätta standardalternativ för detta exempel. Alla alternativflaggor som inte finns i denna ordbok lämnas med sitt standardvärde (som anges avDocTestRunner
optionflags). Som standard är inga alternativ inställda.
DocTestFinder-objekt¶
- class doctest.DocTestFinder(verbose=False, parser=DocTestParser(), recurse=True, exclude_empty=True)¶
En bearbetningsklass som används för att extrahera de
DocTest
s som är relevanta för ett visst objekt, från dess docstring och docstrings för de objekt som ingår.DocTest
s kan extraheras från moduler, klasser, funktioner, metoder, staticmethods, classmethods och properties.Det valfria argumentet verbose kan användas för att visa de objekt som sökts av sökaren. Standardvärdet är
False
(ingen utdata).Det valfria argumentet parser anger objektet
DocTestParser
(eller en direkt ersättare) som används för att extrahera doctests från docstrings.Om det valfria argumentet recurse är false, kommer
DocTestFinder.find()
endast att undersöka det givna objektet, och inte några ingående objekt.Om det valfria argumentet exclude_empty är false, kommer
DocTestFinder.find()
att inkludera tester för objekt med tomma dokumentsträngar.DocTestFinder
definierar följande metod:- find(obj[, name][, module][, globs][, extraglobs])¶
Returnerar en lista över
DocTest
som definieras av objs docstring, eller av någon av dess ingående objekts docstrings.Det valfria argumentet name anger objektets namn; detta namn kommer att användas för att konstruera namn för de returnerade
DocTest
s. Om name inte anges användsobj.__name__
.Den valfria parametern module är den modul som innehåller det angivna objektet. Om modulen inte anges eller är
None
, kommer testfinder att försöka att automatiskt bestämma rätt modul. Objektets modul används:Som standardnamnrymd om globs inte anges.
För att förhindra DocTestFinder från att extrahera DocTests från objekt som importeras från andra moduler. (Inneslutna objekt med andra moduler än modul ignoreras)
För att hitta namnet på den fil som innehåller objektet.
För att hjälpa till att hitta radnumret för objektet i dess fil.
Om module är
False
kommer inget försök att hitta modulen att göras. Detta är oklart och används mest för att testa själva doctest: om module ärFalse
, eller ärNone
men inte kan hittas automatiskt, anses alla objekt tillhöra den (icke-existerande) modulen, så alla objekt som ingår kommer (rekursivt) att sökas efter doctests.Globalerna för varje
DocTest
bildas genom att kombinera globs och extraglobs (bindningar i extraglobs åsidosätter bindningar i globs). En ny ytlig kopia av globals-ordlistan skapas för varjeDocTest
. Om globs inte anges är standardvärdet modulens__dict__
, om den anges, eller{}
annars. Om extraglobs inte anges är standardvärdet{}
.
DocTestParser-objekt¶
- class doctest.DocTestParser¶
En bearbetningsklass som används för att extrahera interaktiva exempel från en sträng och använda dem för att skapa ett
DocTest
-objekt.DocTestParser
definierar följande metoder:- get_doctest(string, globs, name, filename, lineno)¶
Extrahera alla doctest-exempel från den angivna strängen och samla dem i ett
DocTest
-objekt.globs, name, filename och lineno är attribut för det nya
DocTest
-objektet. Se dokumentationen förDocTest
för mer information.
- get_examples(string, name='<string>')¶
Extraherar alla doctest-exempel från den angivna strängen och returnerar dem som en lista med
Example
-objekt. Radnummer är 0-baserade. Det valfria argumentet name är ett namn som identifierar den här strängen och används endast för felmeddelanden.
- parse(string, name='<string>')¶
Dela upp den angivna strängen i exempel och mellanliggande text, och returnera dem som en lista med omväxlande
Example
s och strängar. Radnumren förExample
s är 0-baserade. Det valfria argumentet name är ett namn som identifierar den här strängen och används endast för felmeddelanden.
TestResults-objekt¶
DocTestRunner-objekt¶
- class doctest.DocTestRunner(checker=None, verbose=None, optionflags=0)¶
En bearbetningsklass som används för att exekvera och verifiera de interaktiva exemplen i en
DocTest
.Jämförelsen mellan förväntade utdata och faktiska utdata görs av en
OutputChecker
. Denna jämförelse kan anpassas med ett antal alternativflaggor; se avsnitt Flaggor för alternativ för mer information. Om optionsflaggorna är otillräckliga kan jämförelsen också anpassas genom att skicka en underklass avOutputChecker
till konstruktören.Testlöparens displayutmatning kan styras på två sätt. För det första kan en utdatafunktion skickas till
run()
; denna funktion kommer att anropas med strängar som ska visas. Standardvärdet ärsys.stdout.write
. Om det inte är tillräckligt att fånga utdata kan visningsutdata också anpassas genom att subklassa DocTestRunner och åsidosätta metodernareport_start()
,report_success()
,report_unexpected_exception()
ochreport_failure()
.Det valfria nyckelordsargumentet checker anger objektet
OutputChecker
(eller en ersättare) som ska användas för att jämföra förväntade utdata med faktiska utdata för doctest-exempel.Det valfria nyckelordsargumentet verbose styr
DocTestRunner
s ordrikedom. Om verbose ärTrue
, skrivs information ut om varje exempel, allteftersom det körs. Om verbose ärFalse
skrivs endast misslyckanden ut. Om verbose är ospecificerat, ellerNone
, så används verbose-utmatning om kommandoradsväxeln-v
används.Det valfria nyckelordsargumentet optionflags kan användas för att styra hur testlöparen jämför förväntade resultat med faktiska resultat och hur den visar misslyckanden. För mer information, se avsnitt Flaggor för alternativ.
Testlöparen samlar in statistik. Det sammanlagda antalet försök, misslyckade och överhoppade exempel är också tillgängligt via attributen
tries
,failures
ochskips
. Metodernarun()
ochsummarize()
returnerar en instans avTestResults
.DocTestRunner
definierar följande metoder:- report_start(out, test, example)¶
Rapporterar att testlöparen håller på att bearbeta det givna exemplet. Denna metod tillhandahålls för att underklasser till
DocTestRunner
ska kunna anpassa sin utdata; den ska inte anropas direkt.exempel är det exempel som ska bearbetas. test är testet som innehåller example. out är den utdatafunktion som skickades till
DocTestRunner.run()
.
- report_success(out, test, example, got)¶
Rapportera att det givna exemplet kördes framgångsrikt. Denna metod tillhandahålls för att underklasser till
DocTestRunner
ska kunna anpassa sin utdata; den ska inte anropas direkt.example är exemplet som ska bearbetas. got är den faktiska utmatningen från exemplet. test är testet som innehåller example. out är den utdatafunktion som skickades till
DocTestRunner.run()
.
- report_failure(out, test, example, got)¶
Rapportera att det givna exemplet misslyckades. Den här metoden tillhandahålls för att underklasser till
DocTestRunner
ska kunna anpassa sin utdata; den ska inte anropas direkt.example är exemplet som ska bearbetas. got är den faktiska utmatningen från exemplet. test är testet som innehåller example. out är den utdatafunktion som skickades till
DocTestRunner.run()
.
- report_unexpected_exception(out, test, example, exc_info)¶
Rapportera att det givna exemplet gav upphov till ett oväntat undantag. Denna metod tillhandahålls för att underklasser till
DocTestRunner
ska kunna anpassa sina utdata; den ska inte anropas direkt.example är det exempel som ska bearbetas. exc_info är en tupel som innehåller information om det oväntade undantaget (som returneras av
sys.exc_info()
). test är testet som innehåller exempel. out är den utdatafunktion som skickades tillDocTestRunner.run()
.
- run(test, compileflags=None, out=None, clear_globs=True)¶
Kör exemplen i test (ett
DocTest
-objekt) och visa resultaten med hjälp av skrivarfunktionen out. Returnerar en instans avTestResults
.Exemplen körs i namnrymden
test.globs
. Om clear_globs är true (standard) kommer detta namnrymd att rensas efter att testet har körts, för att hjälpa till med skräpsamlingen. Om du vill undersöka namnrymden efter att testet har slutförts använder du clear_globs=False.compileflags anger den uppsättning flaggor som ska användas av Python-kompilatorn när exemplen körs. Om den inte anges kommer den som standard att använda den uppsättning flaggor för framtida import som gäller för globs.
Utdata för varje exempel kontrolleras med hjälp av
DocTestRunner
:s utdatakontroll och resultaten formateras medDocTestRunner.report_*()
-metoderna.
- summarize(verbose=None)¶
Skriv ut en sammanfattning av alla testfall som har körts av denna DocTestRunner, och returnera en
TestResults
-instans.Det valfria argumentet verbose styr hur detaljerad sammanfattningen är. Om ordrikhet inte anges används
DocTestRunner
:s ordrikhet.
DocTestParser
har följande attribut:- tries¶
Antal försök till exempel.
- failures¶
Antal misslyckade exempel.
- skips¶
Antal överhoppade exempel.
Tillagd i version 3.13.
OutputChecker-objekt¶
- class doctest.OutputChecker¶
En klass som används för att kontrollera om den faktiska utmatningen från ett doctest-exempel matchar den förväntade utmatningen.
OutputChecker
definierar två metoder:check_output()
, som jämför ett givet par utmatningar och returnerarTrue
om de matchar; ochoutput_difference()
, som returnerar en sträng som beskriver skillnaderna mellan två utmatningar.OutputChecker
definierar följande metoder:- check_output(want, got, optionflags)¶
Returnerar
True
om den faktiska utdata från ett exempel (got) matchar den förväntade utdata (want). Dessa strängar anses alltid matcha om de är identiska; men beroende på vilka alternativflaggor testköraren använder är flera icke-exakta matchningstyper också möjliga. Se avsnitt Flaggor för alternativ för mer information om alternativflaggor.
- output_difference(example, got, optionflags)¶
Returnerar en sträng som beskriver skillnaderna mellan det förväntade utfallet för ett visst exempel (example) och det faktiska utfallet (got). optionflags är den uppsättning optionsflaggor som används för att jämföra want och got.
Felsökning¶
Doctest tillhandahåller flera mekanismer för felsökning av doctest-exempel:
Flera funktioner konverterar doctests till körbara Python-program, som kan köras under Pythons debugger,
pdb
.Klassen
DebugRunner
är en underklass tillDocTestRunner
som skapar ett undantag för det första misslyckade exemplet och innehåller information om det exemplet. Denna information kan användas för att utföra felsökning av exemplet efteråt.De
unittest
-fall som genereras avDocTestSuite()
stöderdebug()
-metoden som definieras avunittest.TestCase
.Du kan lägga till ett anrop till
pdb.set_trace()
i ett doctest-exempel, och du kommer att hamna i Pythons debugger när den raden körs. Sedan kan du inspektera aktuella värden för variabler och så vidare. Anta till exempel atta.py
innehåller just den här modulen docstring:""" >>> def f(x): ... g(x*2) >>> def g(x): ... print(x+3) ... import pdb; pdb.set_trace() >>> f(3) 9 """
Då kan en interaktiv Python-session se ut så här:
>>> import a, doctest >>> doctest.testmod(a) --Return-- > <doctest a[1]>(3)g()->None -> import pdb; pdb.set_trace() (Pdb) list 1 def g(x): 2 print(x+3) 3 -> import pdb; pdb.set_trace() [EOF] (Pdb) p x 6 (Pdb) step --Return-- > <doctest a[0]>(2)f()->None -> g(x*2) (Pdb) list 1 def f(x): 2 -> g(x*2) [EOF] (Pdb) p x 3 (Pdb) step --Return-- > <doctest a[2]>(1)?()->None -> f(3) (Pdb) cont (0, 3) >>>
Funktioner som konverterar doctests till Python-kod och eventuellt kör den syntetiserade koden under felsökaren:
- doctest.script_from_examples(s)¶
Konvertera text med exempel till ett skript.
Argument s är en sträng som innehåller doctest-exempel. Strängen konverteras till ett Python-skript, där doctest-exemplen i s konverteras till vanlig kod och allt annat konverteras till Python-kommentarer. Det genererade skriptet returneras som en sträng. Till exempel
import doctest print(doctest.script_from_examples(r""" Set x and y to 1 and 2. >>> x, y = 1, 2 Print their sum: >>> print(x+y) 3 """))
visar:
# Ställ in x och y till 1 och 2. x, y = 1, 2 # # Skriv ut deras summa: print(x+y) # Förväntat: ## 3
Denna funktion används internt av andra funktioner (se nedan), men kan också vara användbar när du vill omvandla en interaktiv Python-session till ett Python-skript.
- doctest.testsource(module, name)¶
Konvertera doctestet för ett objekt till ett skript.
Argument module är ett modulobjekt, eller ett punktat namn på en modul, som innehåller det objekt vars doctests är av intresse. Argument name är namnet (inom modulen) på objektet med de doctests som är av intresse. Resultatet är en sträng som innehåller objektets dokumentsträng konverterad till ett Python-skript, enligt beskrivningen för
script_from_examples()
ovan. Om till exempel modulena.py
innehåller en toppnivåfunktionf()
, så ärimport a, doctest print(doctest.testsource(a, "a.f"))
skriver ut en skriptversion av funktionen
f()
’s docstring, med doctests konverterade till kod och resten placerade i kommentarer.
- doctest.debug(module, name, pm=False)¶
Felsök doctesterna för ett objekt.
Argumenten module och name är desamma som för funktionen
testsource()
ovan. Det syntetiserade Python-skriptet för det namngivna objektets docstring skrivs till en temporär fil, och sedan körs filen under kontroll av Python-debuggern,pdb
.En ytlig kopia av
module.__dict__
används för både lokal och global exekveringskontext.Det valfria argumentet pm styr om felsökning efter avslutad körning ska användas. Om pm har ett sant värde körs skriptfilen direkt och felsökaren blir inblandad endast om skriptet avslutas genom att ett ohanterat undantag uppstår. Om så är fallet aktiveras post-mortem-felsökning via
pdb.post_mortem()
, som skickar spårningsobjektet från det ohanterade undantaget. Om pm inte anges, eller är false, körs skriptet under debuggern från början, genom att skicka ett lämpligtexec()
-anrop tillpdb.run()
.
- doctest.debug_src(src, pm=False, globs=None)¶
Felsök doctesterna i en sträng.
Detta är som funktionen
debug()
ovan, förutom att en sträng som innehåller doctest-exempel anges direkt via argumentet src.Det valfria argumentet pm har samma betydelse som i funktionen
debug()
ovan.Det valfria argumentet globs anger en ordbok som ska användas som både lokalt och globalt exekveringskontext. Om det inte anges, eller
None
, används en tom ordbok. Om det anges används en ytlig kopia av ordlistan.
Klassen DebugRunner
, och de speciella undantag som den kan ge upphov till, är av störst intresse för utvecklare av testramverk och kommer endast att beskrivas översiktligt här. Se källkoden, och särskilt DebugRunner
s docstring (som är ett doctest!) för mer information:
- class doctest.DebugRunner(checker=None, verbose=None, optionflags=0)¶
En underklass till
DocTestRunner
som ger upphov till ett undantag så snart ett fel uppstår. Om ett oväntat undantag inträffar, skapas ettUnexpectedException
-undantag som innehåller testet, exemplet och det ursprungliga undantaget. Om utdata inte stämmer överens skapas ettDocTestFailure
-undantag som innehåller testet, exemplet och den faktiska utdatan.För information om konstruktörens parametrar och metoder, se dokumentationen för
DocTestRunner
i avsnitt Avancerat API.
Det finns två undantag som kan uppstå i DebugRunner
-instanser:
- exception doctest.DocTestFailure(test, example, got)¶
Ett undantag som tas upp av
DocTestRunner
för att signalera att ett doctest-exempels faktiska resultat inte stämde överens med det förväntade resultatet. Argumenten i konstruktorn används för att initiera attributen med samma namn.
DocTestFailure
definierar följande attribut:
- DocTestFailure.got¶
Exemplets faktiska utdata.
- exception doctest.UnexpectedException(test, example, exc_info)¶
Ett undantag som skapas av
DocTestRunner
för att signalera att ett doctest-exempel skapade ett oväntat undantag. Argumenten i konstruktorn används för att initiera attributen med samma namn.
UnexpectedException
definierar följande attribut:
- UnexpectedException.exc_info¶
En tupel som innehåller information om det oväntade undantaget, som returneras av
sys.exc_info()
.
Soapbox¶
Som nämndes i inledningen har doctest
vuxit till att ha tre primära användningsområden:
Kontroll av exempel i docstrings.
Regressionstestning.
Exekverbar dokumentation / litterat test.
Dessa användningsområden har olika krav, och det är viktigt att skilja dem åt. Framför allt blir dokumentationen dålig om man fyller den med obskyra testfall.
När du skriver en docstring ska du välja docstring-exempel med omsorg. Det här är en konst som måste läras - det kanske inte är naturligt i början. Exemplen bör tillföra dokumentationen ett verkligt värde. Ett bra exempel kan ofta vara värt många ord. Om du gör det med omsorg kommer exemplen att vara ovärderliga för dina användare och betala tillbaka den tid det tar att samla in dem många gånger om när åren går och saker och ting förändras. Jag är fortfarande förvånad över hur ofta ett av mina doctest
-exempel slutar fungera efter en ”harmlös” förändring.
Doctest är också ett utmärkt verktyg för regressionstestning, särskilt om man inte snålar med den förklarande texten. Genom att varva prosa och exempel blir det mycket lättare att hålla reda på vad som faktiskt testas och varför. När ett test misslyckas kan bra prosa göra det mycket lättare att räkna ut vad problemet är och hur det ska åtgärdas. Det är sant att man kan skriva omfattande kommentarer i kodbaserade tester, men det är få programmerare som gör det. Många har upptäckt att man får mycket tydligare tester om man istället använder sig av doctest-metoder. Kanske beror det helt enkelt på att doctest gör det lite enklare att skriva prosa än att skriva kod, medan det är lite svårare att skriva kommentarer i kod. Jag tror att det går djupare än så: den naturliga inställningen när man skriver ett doctest-baserat test är att man vill förklara de små detaljerna i sin programvara och illustrera dem med exempel. Detta leder i sin tur naturligt till testfiler som börjar med de enklaste funktionerna och logiskt går vidare till komplikationer och kantfall. Resultatet blir en sammanhängande berättelse i stället för en samling isolerade funktioner som testar isolerade bitar av funktionalitet till synes slumpmässigt. Det är en annan attityd som ger andra resultat och suddar ut skillnaden mellan att testa och att förklara.
Regressionstester bör helst begränsas till särskilda objekt eller filer. Det finns flera alternativ för att organisera tester:
Skriv textfiler som innehåller testfall som interaktiva exempel och testa filerna med
testfile()
ellerDocFileSuite()
. Detta rekommenderas, men är lättast att göra för nya projekt som redan från början är utformade för att använda doctest.Definiera funktioner med namnet
_regrtest_topic
som består av enskilda dokumentsträngar som innehåller testfall för de namngivna ämnena. Dessa funktioner kan inkluderas i samma fil som modulen, eller separeras till en separat testfil.Definiera en
__test__
-ordbok som mappar från regressionstestämnen till dokumentsträngar som innehåller testfall.
När du har placerat dina tester i en modul kan modulen själv vara testköraren. När ett test misslyckas kan du ordna så att din testkörare bara kör om det misslyckade testet medan du felsöker problemet. Här är ett minimalt exempel på en sådan testlöpare:
if __name__ == '__main__':
import doctest
flags = doctest.REPORT_NDIFF|doctest.FAIL_FAST
if len(sys.argv) > 1:
name = sys.argv[1]
if name in globals():
obj = globals()[name]
else:
obj = __test__[name]
doctest.run_docstring_examples(obj, globals(), name=name,
optionflags=flags)
else:
fail, total = doctest.testmod(optionflags=flags)
print(f"{fail} failures out of {total} tests")
Fotnoter