introduction to programming ibbm101/fall18/... · lecture overview •debugging •exception...

Post on 04-Oct-2020

2 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Lecture#08– TestingandDebugging

AykutErdem,Fuat Akal&AydınKaya//Fall2018

BBM101IntroductiontoProgrammingI

TheAdventuresofSherlockHolmes(1939)

Lasttime… Sorting,ListComprehension,Visualization

Datavisualization

Sortingprint("hamlet:", hamlet)

print("sorted(hamlet):", sorted(hamlet))print("hamlet:", hamlet)

print("hamlet.sort():", hamlet.sort())print("hamlet:", hamlet)

M = MonthAverages('Ithaca') bar(range(12),M,facecolor='magenta') xlim(-.2,12)ylabel('Average Hours of Sunlight') title(A.City,fontsize=16)show()

2

[i*2 for i in range(3)]

Listcomprehension

LectureOverview• Debugging• ExceptionHandling• Testing

3

Disclaimer:Muchofthematerialandslidesforthislecturewereborrowedfrom—R.Anderson,M.ErnstandB.HoweinUniversityofWashingtonCSE140

LectureOverview• Debugging• ExceptionHandling• Testing

4https://www.reddit.com/r/ProgrammerHumor/comments/1r0cw7/the_5_stages_of_debugging/

TheProblem

Whatyouwantyourprogramtodo Whatyourprogramdoes

Notthesame!

5

Thereisabug!

WhatisDebugging?• GraceHopperwasoneofU.S.’sfirstprogrammers.• ShefoundamothintheMarkIcomputer,whichwascausingerrors,andcalleditacomputer“bug”

• Thus,theworddebuggingiscoinedJ

6

DebuggingTools• Pythonerrormessage• assert• print• Pythoninterpreter• PythonTutor(http://pythontutor.com)• Pythondebugger• Besttool:

7

1. Thescientificmethod2. Divideandconquer

Ifyoumasterthose,youwillfinddebuggingeasy,andpossiblyenjoyable;-)

8

TwoKeyIdeas

TheScientificMethod

1. Createahypothesis

2. Designanexperimenttotestthathypothesis– Ensurethatityieldsinsight

3. Understandtheresultofyourexperiment– Ifyoudon’tunderstand,thenpossiblysuspendyourmainlineofworktounderstandthat

9

TheScientificMethod

Tips:

• Besystematic– Neverdoanythingifyoudon'thaveareason– Don’tjustflail

• Randomguessingislikelytodigyouintoadeeperhole

• Don’tmakeassumptions(verifythem)

10

ExampleExperiments1. Analternateimplementationofafunction– Runallyourtestcasesafterward

2. Anew,simplertestcase– Examples:smallerinput,ortestafunctioninisolation

– Canhelpyouunderstandthereasonforafailure

11

YourScientificNotebookRecordeverythingyoudo• Specificinputsandoutputs(bothexpectedandactual)• Specificversionsoftheprogram

– Ifyougetstuck,youcanreturntosomethingthatworks– Youcanwritemultipleimplementationsofafunction

• Whatyouhavealreadytried• Whatyouareinthemiddleofdoingnow

– Thismaylooklikeastack!

• Whatyouaresureof,andwhy

Yournotebookalsohelpsifyouneedtogethelporreproduceyourresults.

12

ReadtheErrorMessage

Traceback (most recent call last):File "nx_error.py", line 41, in <module>print(friends_of_friends(rj, myval))

File "nx_error.py", line 30, in friends_of_friendsf = friends(graph, user)

File "nx_error.py", line 25, in friendsreturn set(graph.neighbors(user))#

File "/Library/Frameworks/…/graph.py", line 978, in neighborsreturn list(self.adj[n])

TypeError: unhashable type: 'list'

Listofallexceptions(errors):http://docs.python.org/3/library/exceptions.html#bltin-exceptionsTwootherresources,withmoredetailsaboutafewoftheerrors:http://inventwithpython.com/appendixd.htmlhttp://www.cs.arizona.edu/people/mccann/errors-python

Callstackortraceback

Firstfunctionthatwascalled(<module> meanstheinterpreter)

Secondfunctionthatwascalled

Lastfunctionthatwascalled(thisonesufferedanerror)

Theerrormessage:dauntingbutuseful.Youneedtounderstand:• theliteralmeaningof

theerror• theunderlying

problemscertainerrorstendtosuggest13

CommonErrorTypes

• AssertionError– Raisedwhenanassertstatementfails.

• IndexError– Raisedwhenasequencesubscriptisoutofrange.

• KeyError– Raisedwhenamapping(dictionary)keyisnotfoundinthesetofexistingkeys.

• KeyboardInterrupt– Raisedwhentheuserhitstheinterruptkey(normallyControl-CorDelete).

14

CommonErrorTypes

• NameError– Raisedwhenalocalorglobalnameisnotfound.

• SyntaxError– Raisedwhentheparserencountersasyntaxerror.

• IndentationError– Baseclassforsyntaxerrorsrelatedtoincorrectindentation.

• TypeError– Raisedwhenanoperationorfunctionisappliedtoanobjectofinappropriatetype.

15

DivideandConquer

• Whereisthedefect(or“bug”)?• Yourgoalistofindtheoneplacethatitis• Findingadefectisoftenharderthanfixingit

• Initially,thedefectmightbeanywhereinyourprogram– Itisimpracticaltofinditifyouhavetolookeverywhere

• Idea:bitbybitreducethescopeofyoursearch• Eventually,thedefectislocalizedtoafewlinesoroneline– Thenyoucanunderstandandfixit

16

DivideandConquer

• 4waystodivideandconquer:– Intheprogramcode– Intestcases– Duringtheprogramexecution– Duringthedevelopmenthistory

17

• Localizethedefecttopartoftheprogram– e.g.,onefunction,oronepartofafunction

• Codethatisn’texecutedcannotcontainthedefect

18

DivideandConquerintheProgramCode

Threeapproaches:1. Testonefunctionatatime

19

DivideandConquerintheProgramCode

Threeapproaches:2. Addassertionsorprintstatements– Thedefectisexecutedbeforethefailingassertion(andmaybeafterasucceedingassertion)

20

DivideandConquerintheProgramCode

Threeapproaches:3. Splitcomplexexpressionsintosimplerones

Example:Failureinresult = set({graph.neighbors(user)})

Changeittonbors = graph.neighbors(user)

nbors_set = {nbors}

result = set(nbors_set)

Theerroroccursonthe“nbors_set ={nbors}"line21

DivideandConquerintheProgramCode

DivideandConquerinTestCases

• Yourprogramfailswhenrunonsomelargeinput– It’shardtocomprehendtheerrormessage– Thelogofprintstatementoutputisoverwhelming

• Tryasmallerinput– Chooseaninputwithsomebutnotallcharacteristicsofthelargeinput

– Example:duplicates,zeroesindata,…

22

DivideandConquerinExecutionTimeviaPrint(or“logging”)Statements

• Asequenceofprint statementsisarecordoftheexecutionofyourprogram

• Theprint statementsletyouseeandsearchmultiplemomentsintime

• Printstatementsareausefultechnique,inmoderation• Bedisciplined

– Toomuchoutputisoverwhelmingratherthaninformative– Rememberthescientificmethod:haveareason(ahypothesistobetested)foreachprintstatement

– Don’tonly useprintstatements

23

DivideandConquerinDevelopmentHistory• Thecodeusedtowork(forsometestcase)• Thecodenowfails• Thedefectisrelatedtosomelineyouchanged

• Thisisusefulonlyifyoukeptaversionofthecodethatworked(usegoodnames!)

• Thisismostusefulifyouhavemadefewchanges• Moral:testoften!– Fewerlinestocompare– Yourememberwhatyouwerethinking/doingrecently

24

AMetaphorAboutDebugging

Ifyourcodedoesn’tworkasexpected,thenbydefinitionyoudon’tunderstandwhatisgoingon.

• You’relostinthewoods.• You’rebehindenemylines.• Allbetsareoff.• Don’ttrustanyoneoranything.

Don’tpressonintounexploredterritory-- gobackthewayyoucame! (andleavebreadcrumbs!)

You’retryingto“advancethefrontlines,”not“trailblaze”25

• Thegameistogofrom“workingtoworking”• Whensomethingdoesn’twork,STOP!

– It’swildoutthere!• FIRST:Gobacktothelastsituationthatworkedproperly.

– Rollbackyourrecentchangesandverifythateverythingstillworksasexpected.

– Don’tmakeassumptions– bydefinition,youdon’tunderstandthecodewhensomethinggoeswrong,soyoucan’ttrustyourassumptions.

– Youmayfindthatevenwhatpreviouslyworkednowdoesn’t– Perhapsyouforgottoconsidersome“innocent”orunintentional

change,andnoweventestedcodeisbroken

26

Time-SavingTrick:MakeSureYouareDebuggingtheRightProblem

ABadTimeline

• Aworks,socelebratealittle• NowtryB• Bdoesn’twork• ChangeBandtryagain• ChangeBandtryagain• ChangeBandtryagain…

27

https://xkcd.com/1739/

ABadTimeline

• Aworks,socelebratealittle• NowtryB• Bdoesn’twork• ChangeBandtryagain• ChangeBandtryagain• ChangeBandtryagain…

28

fromgiphy.com

ABetterTimeline• Aworks,socelebratealittle• NowtryB• Bdoesn’twork• RollbacktoA• DoesAstillwork?

– Yes:FindA’thatissomewherebetweenAandB– No:Youhaveunintentionallychangedsomethingelse,andthere’sno

pointfutzingwithBatall!

These“innocent”andunnoticedchangeshappenmorethanyouwouldthink!• Youaddacomment,andtheindentationchanges.• Youaddaprintstatement,andafunctionisevaluatedtwice.• Youmoveafile,andthewrongoneisbeingread• Youareonadifferentcomputer,andthelibraryisadifferentversion

29

OnceYouareonSolidGroundYoucanSetOutAgain• Onceyouhavesomethingthatworksandsomethingthatdoesn’twork,itisonlyamatteroftime

• Youjustneedtoincrementallychangetheworkingcodeintothenon-workingcode,andtheproblemwillrevealitself.

• Variation:Perhapsyourcodeworkswithoneinput,butfailswithanother.Incrementallychangethegoodinputintothebadinputtoexposetheproblem.

30

SimpleDebuggingToolsprint

– showswhatishappeningwhetherthereisaproblemornot

– doesnotstopexecutionassert

– Raisesanexceptionifsomeconditionisnotmet– Doesnothingifeverythingworks– Example:assert len(rj.edges()) == 16

– Usethisliberally!Notjustfordebugging!

31

32

33

LectureOverview• Debugging• ExceptionHandling• Testing

34

WhatisanException?• Anexceptionisanabnormalcondition(andthusrare)thatarisesinacodesequenceatruntime.

• Forinstance:– Dividinganumberbyzero– Accessinganelementthatisoutofboundsofanarray– Attemptingtoopenafilewhichdoesnotexist

35

WhatisanException?• Whenanexceptionalconditionarises,anobjectrepresentingthatexceptioniscreatedandthrowninthecodethatcausedtheerror

• Anexceptioncanbecaughttohandleitorpassiton

• Exceptionscanbegeneratedbytherun-timesystem,ortheycanbemanuallygeneratedbyyourcode

36

WhatisanException?test = [1,2,3]test[3]

37

IndexError: list index out of range

WhatisanException?successFailureRatio = numSuccesses/numFailures

print('The success/failure ratio is', successFailureRatio)

print('Now here')

38

ZeroDivisionError: integer division or modulo by zero

WhatisanException?val = int(input('Enter an integer: '))

print('The square of the number', val**2)

> Enter an integer: asd

39

ValueError: invalid literal for int() with base 10: 'asd'

HandlingExceptions• Exception mechanism gives the programmer achanceto dosomething against anabnormal condition.

• Exception handling isperforming anaction inresponseto anexception.

• This action may be:– Exiting the program– Retrying the action with or without alternative data– Displaying anerror message and warning user to dosomething

– ....

40

HandlingExceptionstry:

successFailureRatio = numSuccesses/numFailures

print('The S/F ratio is', successFailureRatio)

except ZeroDivisionError:

print('No failures, so the S/F is undefined.')

print('Now here')

41

• Uponenteringthetry block,theinterpreterattemptstoevaluatetheexpressionnumSuccesses/numFailures.

• Ifexpressionevaluationissuccessful,theassignmentisdoneandtheresultisprinted.

• If,however,aZeroDivisionError exceptionisraised,theprintstatementintheexcept blockisexecuted.

while True: val = input('Enter an integer: ') try:

val = int(val) print('The square of the number', val**2) break #to exit the while loop

except ValueError: print(val, 'is not an integer')

42

HandlingExceptions

ChecksforwhetherValueError exceptionisraisedornot

KeywordsofExceptionHandling• There are five keywords inPython to deal withexceptions:try,except,else,raise and finally.

• try:Creates ablock to monitor if any exceptionoccurs.

• except:Follows the try block and catches anyexception which isthrown within it.

43

AreThereManyExceptionsinPython?

• Yes,someofthemare…– Exception– ArithmeticError– OverflowError– ZeroDivisonError– EOFError– NameError– IOError– SyntaxError

44

Listofallexceptions(errors):http://docs.python.org/3/library/exceptions.html#bltin-exceptions

MultipleexceptStatements

45

• It ispossible that more than one exception canbethrown inacode block.– Wecanusemultipleexcept clauses

• Whenanexceptionisthrown,eachexceptstatementisinspectedinorder,andthefirstonewhosetypematches thatoftheexceptionisexecuted.– Type matching means that the exception thrown must beanobject ofthe same class or asub-class ofthe declared classinthe except statement

• Afteroneexcept statementexecutes,theothersarebypassed.

MultipleexceptStatements

46

try:

Youdoyouroperationshere;except Exception-1:

Executethisblock.except Exception-2:

Executethisblock.except (Exception-3[, Exception-4[,...ExceptionN]]]):

Ifthereisanyexceptionfromthegivenexceptionlist,thenexecutethisblock.

except (ValueError, TypeError):…

Theexceptblockwillbeenteredifanyofthelistedexceptions israisedwithinthetryblock

MultipleexceptStatementstry:

f = open('outfile.dat', 'w')dividend = 5divisor = 0division = dividend / divisorf.write(str(division))

except IOError:print("I can't open the file!")

except ZeroDivisionError:print("You can't divide by zero!")

47

Youcan'tdividebyzero!

MultipleexceptStatementstry:

f = open('outfile.dat', 'w')dividend = 5divisor = 0division = dividend / divisorf.write(str(division))

except Exception:print("Exception occured and handled!")

except IOError:print("I can't open the file!")

except ZeroDivisionError:print("You can't divide by zero!")

48

Exceptionoccured andhandled!

MultipleexceptStatementstry:

f = open('outfile.dat', 'w')dividend = 5divisor = 0division = dividend / divisorf.write(str(division))

except:print("Exception occured and handled!")

except IOError:print("I can't open the file!")

except ZeroDivisionError:print("You can't divide by zero!")

49

SyntaxError: default 'except:' must be last

except-elseStatements

50

try:You do your operations here

except: Execute this block.

else: If there is no exception, execute this block.

try:f = open(arg, 'r')

except IOError:print('cannot open', arg)

else:print(arg, 'has', len(f.readlines()), 'lines')

finally Statement

51

• finally creates ablock ofcode that will beexecuted afteratry/except block hascompleted and before the codefollowing the try/except block

• finally block isexecuted whether or notexception isthrown

• finally block isexecuted whether or notexception iscaught

• It isused to guarantee that acode block will beexecuted inanycondition.

finally Statement

52

Youcanuseittocleanupfiles,databaseconnections,etc.

try:You do your operations here

except: Execute this block.

finally: This block will definitely be executed.

try: file = open('out.txt', 'w') do something…

finally: file.close()os.path.remove('out.txt')

Nestedtry Blocks• When anexception occurs insideatry block;

– If the try block does nothave amatching except,then the outertry statement’s except clauses are inspected for amatch

– If amatching except isfound,that except block isexecuted– If no matching except exists,execution flow continues to find a

matching except by inspecting the outer try statements– If amatching except cannot befound atall,the exception will be

caught by Python’s exception handler.

• Execution flow never returns to the line that exceptionwas thrown.This means,anexception iscaught andexcept block isexecuted,the flow will continue with thelines following this except block

53

Let’s clarify itonvarious scenarios

54

try:statement1try:

statement2except Exception1:

statement3except Exception2:

statement4;try:

statement5except Exception3:

statement6statement7;

except Exception3:statement8

statement9;

Information: Exception1andException2aresubclassesofException3

Question:Whichstatementsareexecutedif1- statement1throwsException12- statement2throwsException13- statement2throwsException34- statement2throwsException1andstatement3throws Exception2

Scenario:statement1throws Exception1

55

try:statement1try:

statement2except Exception1:

statement3except Exception2:

statement4;try:

statement5except Exception3:

statement6statement7;

except Exception3:statement8

statement9;

Exception1Step1:Exceptionisthrown

Step2:except clauses ofthetryblockareinspectedforamatching except statement.Exception3issuperclassofException1,soitmatches.

Step3:statement8isexecuted,exceptionishandledandexecutionflowwillcontinuebypassingthefollowing except clauses

Step4:statement9isexecuted

Scenario:statement2throws Exception1

56

try:statement1try:

statement2except Exception1:

statement3except Exception2:

statement4;try:

statement5except Exception3:

statement6statement7;

except Exception3:statement8

statement9;

Exception1Step1:Exceptionisthrown

Step2:except clauses ofthetryblockareinspectedforamatching except statement.Firstclausecatchestheexception

Step3:statement3isexecuted,exceptionishandled

Step4:executionflowwillcontinuebypassingthefollowing except clauses.statement5isexecuted.

Step5:Assumingnoexceptionisthrownbystatement5,programcontinueswithstatement7andstatement9.

Scenario:statement2throws Exception3

57

try:statement1try:

statement2except Exception1:

statement3except Exception2:

statement4;try:

statement5except Exception3:

statement6statement7;

except Exception3:statement8

statement9;

Exception3Step1:Exceptionisthrown

Step2:except clauses ofthetryblockareinspectedforamatching except statement.Noneofthese except clauses matchException3

Step3:except clauses oftheoutertrystatementareinspectedforamatching except .Exception3iscatchedandstatement8isexecuted

Step4:statement9isexecuted

Scenario:statement2throws Exception1and statement3throws Exception2

58

try:statement1try:

statement2except Exception1:

statement3except Exception2:

statement4;try:

statement5except Exception3:

statement6statement7;

except Exception3:statement8

statement9;

Exception1Step1:Exceptionisthrown

Step2:Exceptioniscatchedandstatement3isexecuted.

Step3:statement3throwsanewexception

Step5:statement9isexecuted

Exception2

Step4:Except clauses oftheoutertrystatementareinspectedforamatching except.Exception2iscatchedandstatement8isexecuted

raise Statement• Youcanraiseexceptionsbyusingtheraisestatement.

• Thesyntaxisasfollows:raise exceptionName(arguments)

59

raise Statementdef getRatios(vect1, vect2):

ratios = []for index in range(len(vect1)):

try:ratios.append(vect1[index]/vect2[index])

except ZeroDivisionError:ratios.append(float('nan')) #nan = Not a Number

except:raise ValueError(’getRatios called with bad arguments’)

return ratios

try:print(getRatios([1.0, 2.0, 7.0, 6.0], [1.0,2.0,0.0,3.0]))print(getRatios([], []))print(getRatios([1.0, 2.0], [3.0]))

except ValueError as msg:print(msg)

60

[1.0, 1.0, nan, 2.0][]getRatios called with bad arguments

raise Statement• AvoidraisingagenericException! Tocatchit,you'llhave

tocatchallothermorespecificexceptionsthatsubclassit.

61

def demo_bad_catch(): try:

raise ValueError('a hidden bug, do not catch this')raise Exception('This is the exception you expect to handle')

except Exception as error:print('caught this error: ' + repr(error))

>>> demo_bad_catch()caught this error: ValueError('a hidden bug, do not catch this',)

raise Statement• andmorespecificcatcheswon'tcatchthegeneralexception:..

62

def demo_no_catch(): try:

raise Exception('general exceptions not caught by specific handling')except ValueError as e:

print('we will not catch e')

>>> demo_no_catch()Traceback (most recent call last):

File "<stdin>", line 1, in <module> File "<stdin>", line 3, in demo_no_catch

Exception: general exceptions not caught by specific handling

CustomExceptions

63

• UserscandefinetheirownexceptionbycreatinganewclassinPython.

• Thisexceptionclasshastobederived,eitherdirectlyorindirectly,fromtheExceptionclass.

• Mostofthebuilt-inexceptionsarealsoderivedformthisclass.

CustomExceptions

class ValueTooSmallError(Exception):"""Raised when the input value is too small"""pass

class ValueTooLargeError(Exception):"""Raised when the input value is too large"""pass

64

CustomExceptions

number = 10 # you need to guess this number

while True:try:

i_num = int(input("Enter a number: "))if i_num < number:

raise ValueTooSmallErrorelif i_num > number:

raise ValueTooLargeErrorbreak

except ValueTooSmallError:print("This value is too small, try again!")

except ValueTooLargeError:print("This value is too large, try again!")

print("Congratulations! You guessed it correctly.")

65

LectureOverview• Debugging• ExceptionHandling• Testing

66

Testing• Programmingtoanalyzedataispowerful• Itisuselessiftheresultsarenotcorrect• Correctnessisfarmoreimportantthanspeed

67

FamousExamples• Ariane 5rocket– OnJune4,1996,themaidenflightoftheEuropeanAriane5launchercrashedabout40secondsaftertakeoff.

– Mediareportsindicatedthattheamountlostwashalfabilliondollars

– Theexplosionwastheresultofasoftwareerror

• Therac-25radiationtherapymachine– In1985aCanadian-builtradiation-treatmentdevicebeganblastingholesthroughpatients'bodies.

68

TestingdoesnotProve Correctness• Edsger Dijkstra:“Programtestingcanbeusedtoshowthepresenceofbugs,butnevertoshowtheirabsence!”

69

Testing=Double-CheckingResults• Howdoyouknowyourprogramisright?– Compareitsoutputtoacorrectoutput

• Howdoyouknowacorrectoutput?– Realdataisbig– Youwroteacomputerprogrambecauseitisnotconvenienttocomputeitbyhand

• Usesmallinputssoyoucancomputebyhand

• Example:standarddeviation– Whataregoodtestsforstd_dev?

70

Testing≠Debugging• Testing:Determiningwhether yourprogramiscorrect– Doesn’tsaywhere orhow yourprogramisincorrect

• Debugging:Locatingthespecificdefectinyourprogram,andfixingit2keyideas:– divideandconquer– thescientificmethod

71

WhatisaTest?

• Atestconsistsof:– aninput:sometimescalled“testdata”– anoracle:apredicate(boolean expression)oftheoutput

72

WhatisaTest?

• Exampletestforsum:– input:[1,2,3]– oracle:resultis6– writethetestas:sum([1, 2, 3]) == 6

• Exampletestforsqrt:– input:3.14– oracle:resultiswithin0.00001of1.772– waystowritethetest:• -0.00001 < sqrt(3.14) – 1.772 < 0.00001• math.abs(sqrt(3.14) – 1.772) < 0.00001

73

TestResults• Thetestpasses ifthebooleanexpressionevaluatestoTrue

• Thetestfails ifthebooleanexpressionevaluatestoFalse

• Usetheassert statement:– assert sum([1, 2, 3]) == 6– assert True doesnothing– assert False crashestheprogramandprintsamessage

74

WheretoWriteTestCases• Atthetoplevel:isruneverytimeyouloadyourprogram

def hypotenuse(a, b):…

assert hypotenuse(3, 4) == 5assert hypotenuse(5, 12) == 13

• Inatestfunction:isrunwhenyouinvokethefunctiondef hypotenuse(a, b):

…def test_hypotenuse():

assert hypotenuse(3, 4) == 5assert hypotenuse(5, 12) == 13

75

AssertionsarenotJustforTestCases• Useassertionsthroughoutyourcode

• Documentswhatyouthinkistrueaboutyouralgorithm

• Letsyouknowimmediatelywhensomethinggoeswrong– Thelongerbetweenacodemistakeandtheprogrammernoticing,theharderitistodebug

76

AssertionsMakeDebuggingEasier• Common,butunfortunate,courseofevents:

– Codecontainsamistake(incorrectassumptionoralgorithm)– Intermediatevalue(e.g.,resultofafunctioncall)isincorrect– Thatvalueisusedinothercomputations,orcopiedintoothervariables

– Eventually,theusernoticesthattheoverallprogramproducesawrongresult

– Whereisthemistakeintheprogram?Itcouldbeanywhere.

• Supposeyouhad10assertionsevenlydistributedinyourcode– Whenonefails,youcanlocalizethemistaketo1/10ofyourcode(thepartbetweenthelastassertionthatpassesandthefirstonethatfails)

77

WheretoWriteAssertions• Functionentry:Areargumentslegal?

– Placeblameonthecallerbeforethefunctionfails

• Functionexit:Isresultcorrect?

• Placeswithtrickyorinterestingcode

• Assertionsareordinarystatements;e.g.,canappearwithinaloop:

for n in myNumbers:assert type(n) == int or type(n) == float

78

Wherenot toWriteAssertions• Don’tclutterthecode

– Sameruleasforcomments

• Don’twriteassertionsthatarecertaintosucceed– Theexistenceofanassertiontellsaprogrammerthatitmightpossiblyfail

• Don’twriteanassertionifthefollowingcodewouldfailinformatively

assert type(name) == strprint("Hello, " + name)

• Writeassertionswheretheymaybeusefulfordebugging

79

WhattoWriteAssertionsAbout• Resultsofcomputations

• Correctly-formeddatastructures

assert 0 <= index < len(mylist)assert len(list1) == len(list2)

80

WhentoWriteTests• Twopossibilities:–Writecodefirst,thenwritetests–Writetestsfirst,thenwritecode

81

WhentoWriteTests• Ifyouwritethecodefirst,youremembertheimplementationwhilewritingthetests– Youarelikelytomakethesamemistakesintheimplementation

82

WhentoWriteTests• Ifyouwritethetestsfirst,youwillthinkmoreaboutthefunctionalitythanaboutaparticularimplementation– Youmightnoticesomeaspectofbehaviorthatyouwouldhavemadeamistakeabout

– Thisisthebetterchoice

83

WritetheWholeTest• Acommonmistake:

1. Writethefunction2. Makeuptestinputs3. Runthefunction4. Usetheresultastheoracle

• Youdidn’twriteatest,butonlyhalfofatest– Createdthetestsinputs,butnottheoracle

• Thetestdoesnotdeterminewhetherthefunctioniscorrect– Onlydeterminesthatitcontinuestobeascorrect(orincorrect)asitwasbefore

84

TestingApproaches• Blackboxtesting- Choosetestdatawithoutlookingatimplementation

• Glassbox(whitebox,clearbox)testing -Choosetestdatawith knowledgeofimplementation

85

InsideKnowledgemightbeNice• Assumethecodebelow:

c = a + bif c > 100

print("Tested”)print("Passed”)

• Creatingatestcasewitha=40andb=70isnotenough– Althougheverylineofthecodewillbeexecuted

• Anothertestcasewitha=40andb=30wouldcompletethetest

86

TestsmightnotRevealanErrorSometimes

def mean(numbers):"""Returns the average of the argument list.

The argument must be a non-empty number list."""return sum(numbers)//len(numbers)

# Testsassert mean([1, 2, 3, 4, 5]) == 3assert mean([1, 2, 3]) == 2

Thisimplementationiselegant,butwrong!

mean([1,2,3,4]) à should return 2.5!!!

87

LastbutnotLeast,Don’tWriteMeaninglessTestsdef mean(numbers):"""Returns the average of the argument list.

The argument must be a non-empty number list."""return sum(numbers)//len(numbers)

Unnecessarytests.Don’twritethese:

mean([1, 2, "hello"])mean("hello")mean([])

88

top related